Mockito.mock什么时候创建部分模拟而不是"full"模拟?



给定此代码:

// Subject.kt
open class Subject(var x: Int) {
constructor(): this(42) {
println("made it")
}
fun doit() {
x += 1
println("did it: $x")
}
}
// Tests.kt
import org.junit.jupiter.api.Test
import org.mockito.Mockito
class Tests {
@Test
fun makeit() {
val mock = Mockito.mock(Subject::class.java)
val details = Mockito.mockingDetails(mock)
println("Is mock: ${details.isMock}")
println("Is spy:  ${details.isSpy}")
mock.doit()
mock.doit()
}
}

运行makeit时,输出为:

Is mock: true
Is spy:  false
did it: 1
did it: 2

这似乎表明正在创建主题的某个实例,但绕过了潜在的关键构造函数逻辑。这与"部分mock"是一致的,但代码没有做任何事情来请求这样的东西。

我发现令人惊讶的是,这是默认行为,因为文档都强烈警告不要使用部分mock。我一直找不到描述mock()何时返回部分mock的文档,因此也不知道如何从类中获得"完整mock"。

因此:

  • Mockito.mock()什么时候创建部分mock
  • Mockito能为一个类创建一个"完整的mock"吗?或者只是为了一个界面
  • 如何申请"全模拟">

通过源代码和试错测试,我得出了以下结论:

  1. 当模拟一个类时,Mockito会创建一个ByteBuddy生成的类的子类的实例,而不调用构造函数=>所有成员数据都是默认值
  2. 开放方法(Java的默认方法;在Kotlin中用open声明(:
    • 默认情况下不调用,并返回返回类型的默认值
    • 当配置CCD_ 5时将被调用
    • 如果创建mock时defaultAnswer设置为CALLS_REAL_METHODS,则将调用
  3. final方法不能被重写=>它们将被正常调用,但它们将看到所有成员数据的默认值

所以,似乎所有的类mock都是部分mock,但由于Java中默认的方法是打开的,所以它们通常看起来像常规mock。默认情况下,它们实际上是常规mock。

这在Kotlin中很快就会显示出来,因为默认情况下方法是final

知道这是如何工作的,处理类模拟就不会那么令人沮丧了!

相关内容

  • 没有找到相关文章

最新更新