给出以下课程(用kotlin编写):
class Target {
fun <R> target(filter: String, mapper: (String) -> R): R = mapper(filter)
}
我能够使用Java测试代码:
@Test
public void testInJava() {
Target mockTarget = Mockito.mock(Target.class);
Mockito.when(mockTarget.target(
argThat(it -> true),
Mockito.argThat(it -> true)
)).thenReturn(100);
assert mockTarget.target("Hello World", it -> 1) == 100;
}
java测试通过了预期的结果,但相同的测试用kotlin编写:
@Test
fun test() {
val mockTarget = Mockito.mock(Target::class.java)
Mockito.`when`(mockTarget.target(
Mockito.argThat<String> { true },
mapper = Mockito.argThat<Function1<String, Int>>({ true }))
).thenReturn(100)
assert(mockTarget.target("Hello World") { 1 } == 100)
}
kotlin版本收到以下异常:
java.lang.IllegalStateException: Mockito.argThat<String> { true } must not be null
为什么会发生这种情况,如何使用Kotlin进行测试?
答案 0 :(得分:1)
我也遇到了同样的问题。
最后,我发现argThat()
将返回null,通常kotlin函数中的参数不接受null类型。
argThat
中ArgumentMatchers.java
的源代码
public static <T> T argThat(ArgumentMatcher<T> matcher) {
reportMatcher(matcher);
return null;
}
您可以看到它return null
。因此,当我们模拟该函数时,它将抛出IllegalStateException,因为argThat
返回null 并且参数不能为null。
这意味着您的功能是:
fun doSomething(arg1: String): Int {
// do something
}
当你这样嘲笑时:
Mockito.`when`(
doSomething(Mockito.argThat<String> { true })
).thenReturn(100)
它将抛出IllegalStateException
因此,您应该这样更改功能:
fun doSomething(arg1: String?): Int {
// do something
}
将“字符串”更改为“字符串?”,使其接受空类型。
我的解决方案是用类定义参数?以便它可以接受null,但我不知道这是否是一个很好的解决方案
答案 1 :(得分:0)
截至撰写本文时,mockito-kotlin的更新时间已超过一年。与所有这些库一样,始终需要不断更新它们,而我也不想卡在一个未维护的库中。
所以我想出了另一种方法来解决argThat
中的null问题,而无需使用任何其他库。
假设我们有一个界面UuidRepository
,如下所示:
interface UuidRepository {
suspend fun Entity save(entity: Entity): Entity
}
类Entity
具有两个属性userId: String
和uuid: String
。
以下代码失败:
Mockito.verify(uuidRepository).save(argThat { it.userId == someValue && it.uuid == "test" })
出现错误:
argThat {it.userId == someValue && it.uuid ==“ test”}不能为空
要解决此问题,我们在模拟中获得所有调用,然后验证所需的调用:
val invocations = Mockito.mockingDetails(uuidRepository).invocations
.filter { setOf("findById", "save").contains(it.method.name) }
.map { it.method.name to it.arguments }
.toMap()
assertThat(invocations).containsKey("save")
val first = invocations["save"]?.first()
assertThat(first).isNotNull
val entity = first as Entity
assertThat(entity.userId).isEqualTo(someValue)
assertThat(entity.uuid).isEqualTo("test")