首页 > 其他分享 >Mockk详解

Mockk详解

时间:2023-03-14 17:45:06浏览次数:42  
标签:Mockk mockk Mother giveMoney 详解 替身 mother fun

简述

  mockk和mockito类似,都是在测试环境下制造test double的测试框架

  在kotlin环境下mockk比mockito更加优秀

mockito在kotlin的缺陷

  mockito的when方法在kotlin是关键字,需要加反引号才能使用

  在kotlin里所有class都是final,而mockito不能mock final的class

  mockito不支持静态方法

引入依赖

  https://mvnrepository.com/artifact/io.mockk/mockk

gradle

testImplementation 'io.mockk:mockk:1.13.3'

maven 

<dependency>
    <groupId>io.mockk</groupId>
    <artifactId>mockk</artifactId>
    <version>1.13.3</version>
    <scope>test</scope>
</dependency>

demo工程 

基本用法

  这里我们以Kid和Mother类举例

class Kid(private val mother: Mother) {
    private var money = 0
    fun wantMoney() {
        money += mother.giveMoney()
    }
}
class Mother {
    fun giveMoney(): Int {
        return 300;
    }
}

制作替身

  使用mockk方法,填入对应替身的泛型,即可制作该Class的替身

mockk<Class>()

  这里制作Mother类的替身

val mother = mockk<Mother>()

打桩

  使用every方法对替身进行打桩,和mockito的when.thenReturn类似,即指定该替身的方法返回值

  我们这里对giveMoney进行打桩,令其返回100

every { mother.giveMoney() } returns 100

  最简单的mockk任务到这里就结束了,接下来就可以进行测试方法和结果断言,完整测试方法如下:

@Test
fun shouldReturn30WhenMotherGiveMoneyIs30() {
    //given
    val mother = mockk<Mother>()
    every { mother.giveMoney() } returns 100
    val kid = Kid(mother)
    //when
    kid.wantMoney()
    //then
    assertEquals(100,kid.money)
}

注解

  和mockito类似,mockk也支持用注解进行初始化

  在成员变量上使用@Mockk注解,代表带回会自动创建该类的替身,然后在BeforeTest的配置中使用

MockKAnnotations.init(this),即可初始化替身

  使用@InjectMockKs注解可初始化测试替身作为构造函数参数的对象

import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import org.junit.jupiter.api.Test
import kotlin.test.BeforeTest
import kotlin.test.assertEquals

class KidTest {

    @MockK
    lateinit var mother: Mother

    @InjectMockKs
    lateinit var kid: Kid

    @BeforeTest
    fun setUp() {
        MockKAnnotations.init(this)
    }

    @Test
    fun shouldReturn30WhenMotherGiveMoneyIs30() {
        //given
        every { mother.giveMoney() } returns 100
        //when
        kid.wantMoney()
        //then
        assertEquals(100, kid.money)
    }
}

verify

  和mockito类似,我们可以使用verify来对替身的方法进行判断,看它有没有被调用过

verify { mother.giveMoney() }

  我们还可以verify该方法是否被调用了一定次数,在verify前加上exactly配置即可

verify(exactly = 0) { mother.giveMoney() }

  如果想验证方法被调用是否满足一定顺序,则可以使用verifySequence 和 verifyOrder

verifySequence {
    mother.inform(any())
    mother.giveMoney()
}
verifyOrder {
    mother.inform(any())
    mother.giveMoney()
}

  前者表示方法的执行一定要按这个顺序一条条执行下去,后者表示中间可以加入其他方法的调用,整体顺序是这样就行

当没有对所有方法打桩时

  现在Mother类有两个方法

class Mother {
    fun giveMoney(): Int {
        return 300;
    }
    fun doSomeThing() {
        println("do some thing")
    }
}

  kid的方法变成这样

class Kid(private val mother: Mother) {
    var money = 0
    fun wantMoney() {
        money += mother.giveMoney()
        mother.doSomeThing()
    }
}

  我们如果只对一个方法进行打桩

class KidTest {

    @MockK
    lateinit var mother: Mother

    @InjectMockKs
    lateinit var kid: Kid

    @BeforeTest
    fun setUp() {
        MockKAnnotations.init(this)
    }

    @Test
    fun shouldReturn30WhenMotherGiveMoneyIs30() {
        //given
        every { mother.giveMoney() } returns 100
        //when
        kid.wantMoney()
        //then
        assertEquals(100, kid.money)
        verify { mother.giveMoney() }
        verify { mother.doSomeThing() }
    }
}

  就会报错

  那是因为mockk要求每一个被调用过的替身对象的方法都要打桩

  那问题来了,如果有100个方法,那要打100次桩吗

relaxed

  在进行制作测试替身时,可以指定relaxed = true,意思是该替身所有方法都不用打桩

val mother = mockk<Mother>(relaxed = true)

  也可以使用注解的方式@RelaxedMockK

@RelaxedMockK
lateinit var mother: Mother
  RelaxUnitFun则是无需为无返回值的方法打桩,仅对有返回值的方法打桩就行

  同样有配置和注解两种方法

val mocker = mockk<Mother>(relaxUnitFun = true)
@MockK(relaxUnitFun = true)
lateinit var mother: Mother

对静态方法mock

  我们使用object对象+@JvmStatic注解的方式进行编写kotlin静态方法

object KotlinUtil {
    @JvmStatic
    fun ok(): String {
        return "UtilKotlin.ok()"
    }
}

  然后创建一个方法去使用这个静态方法

class KotlinUtilUsage {
    fun useKotlinUtil() {
        KotlinUtil.staticDoSomething()
    }
}

  测试的时候,可以直接使用mockkStatic进行mock静态测试,直接使用every进行打桩

class StaticMethodTest {

    @Test
    fun staticMethodTest() {
        //given
        val kotlinUtilUsage = KotlinUtilUsage()
        mockkStatic(KotlinUtil::class)
        every { KotlinUtil.staticDoSomething() } returns "mocked returns"
        //when
        kotlinUtilUsage.useKotlinUtil()
        //then
        verify { KotlinUtil.staticDoSomething() }
    }
}

References

https://blog.csdn.net/ljt2724960661/article/details/118251823

https://medium.com/joe-tsai/mockk-%E4%B8%80%E6%AC%BE%E5%BC%B7%E5%A4%A7%E7%9A%84-kotlin-mocking-library-part-2-4-4be059331110

https://juejin.cn/post/6877824384694747143

https://www.jianshu.com/p/8e392a08d99d

 

 

 

 

 

 

 

 

 

 

 

标签:Mockk,mockk,Mother,giveMoney,详解,替身,mother,fun
From: https://www.cnblogs.com/CNLayton/p/17215656.html

相关文章

  • nginx中proxy_pass各种用法详解
    代理转发规则nginx中配置location代理转发规则的时候不同写法对应不同转发规则。如果proxy_pass使用了URI,当传送请求到后端服务器时,规范化以后的请求路径与配置中的路径......
  • L298N 5V使能跳帽使用详解
      5V使能引脚,即图中5VEnable引脚。该引脚与5VPower引脚息息相关,因此首先需要知道5VPower引脚的功能。L298N的5VPower引脚目的是给L298芯片供电(注意:不是给电机供......
  • 2022 漏洞分析期末试题详解
    环境准备关闭地址随机化用sudochownroot...和sudochmod4755...为q1~q5设置特权q1题解题面:short类型最大值为65535,input的长度高于该值即可造成整数溢......
  • iso9001质量体系认证费用详解
    iso9001质量体系认证费用详解现在很多公司都会进行ISO9001质量管理体系认证,ISO9001认证对企业来说是非常重要的,ISO9001质量管理体系认证与企业的未来发展有关,而且会关系到......
  • Tarjan算法详解
    Tarjan算法介绍TarjanTarjan算法是用于在有向图中求强连通分量的算法这里给出强连通分量的定义:有向图中一个最大的图,使这个图中每个两点都能够互相到达。这个最大的图称......
  • K8S部署应用详解
    #前言首先以SpringBoot应用为例介绍一下k8s的发布步骤。1.从代码仓库下载代码,比如GitLab;2.接着是进行打包,比如使用Maven;3.编写Dockerfile文件,把步骤2产生的包制作成镜像......
  • dirsearch web网站目录扫描工具详解
    文章目录​​1dirsearch介绍​​​​2安装​​​​3实战演练​​​​3.1仅指定网址-u​​​​3.2指定网站语言-e​​​​3.3指定字典-w​​​​3.4递归目录-r​......
  • Python的namedtuple使用详解
    namedtuple又名具名元组,因为普通元组的局限性,不能为元组的数据进行命名,所以我们并不知道一个元组所要表达的意义,所以在这里引入了collections.namedtuple这个工厂函数,来构......
  • 转:numpy中expand_dims()函数详解
    注:本文只是本人的通俗理解,有些专业概念表达不是很清楚,但我相信你读完可以理解该函数并会使用。expand_dims(a,axis)中,a为numpy数组,axis为需添加维度的轴,a.shape将在该轴......
  • 【MySQL】substring_index 函数详解
    【MySQL】substring_index函数详解命令格式stringsubstring_index(string<str>,string<separator>,int<count>)命令说明截取字符串str第count个分隔符之前的字......