【问题标题】:When does Mockito.mock create a partial mock instead of a "full" mock?Mockito.mock 何时创建部分模拟而不是“完整”模拟?
【发布时间】:2019-11-12 20:54:11
【问题描述】:

鉴于此代码:

// 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() 何时返回部分模拟的文档,因此无法弄清楚如何从类中获取“完整模拟”。

所以:

  • Mockito.mock() 何时创建部分模拟?
  • Mockito 可以为类创建“完整模拟”吗?还是只是为了一个界面?
  • 如何请求“完整模拟”?

【问题讨论】:

  • 我会将return of 1 解释为该类未被模拟的标志。 (检查你是否看到println。)如果它被嘲笑它应该返回0。 (除非在 kotlin 中有所不同)。部分模拟是使用spy 创建的。
  • 我更新了问题以显示 Mockito 报告该类已被模拟。我还向doit 添加了第二个调用,以显示“模拟”处于保持状态。
  • 我认为这种行为可能与kotlin 不兼容,因此我将其添加为标签。您是否尝试过其他模拟库(mockito-kotlinmockk)?
  • @second:Doh!我们在 Java 中看到了类似的行为(这就是促使我们进行调查的原因)。但果然,上面代码的 Java 版本创建了预期的模拟。我会做一个更好的复制品。谢谢!
  • 如果您有一个导致问题的 java 示例,请随时添加一个新问题,包括 minimal reproducible example

标签: java kotlin mockito partial-mocks


【解决方案1】:

通过源代码和反复试验,我得出以下结论:

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

因此,似乎所有类模拟都是部分模拟,但由于 Java 中的默认设置是开放方法,因此它们通常看起来像常规模拟。默认情况下,它们是有效常规模拟。

这在 Kotlin 中很快出现,因为方法默认为 final

了解其工作原理可以让处理类模拟变得不那么令人沮丧!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2017-09-05
    • 2011-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    相关资源
    最近更新 更多