简述
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
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