java - 为什么 $MockitoMock$ 实例没有被识别为模拟?

标签 java unit-testing kotlin mockito

我使用 Kotlin、Mockito 和 MockitoJRunner 运行以下简化测试:

open class SomeClassToBeMocked @Inject constructor() {
    fun map(foo: Foo): Bar {...}
}

@Mock
private lateinit var someMock: SomeClassToBeMocked
@InjectMocks
private lateinit var subject: Subject

@Test
fun shouldAssertSomething() {
    val foo = Foo() // from Foo.kt
    val bar = Bar() // from Bar.java from *another module*
    whenever(someMock.map(foo)).thenReturn(bar) // breakpoint[1]

    subject.myMethod(foo)

    verify(someMock).map(foo)
}

此模式适用于代码的其他部分,但不适用于此特定测试,我收到以下错误消息:

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

当我在 breakpoint[1] 处调试代码时,我可以看到 someMock 是 SomeClassToBeMocked$MockitoMock$ 类的实例。此外,如果我尝试在 breakpoint[1] 之前立即调用 someMock.map(foo),它确实会运行原始方法,而不是返回 null 像所有模拟一样。

对这里可能发生的事情有什么想法吗?

UPDATE-1:我已检查了错误消息中选项 1 的所有可能性。我也尝试过mock(SomeClassToBeMocked::class.java)并得到相同的错误消息。这种情况在一些最简单的类中经常发生,只有一个公共(public)方法仅将对象 A 转换为对象 B。

UPDATE-2:如果有什么区别的话,我只是注意到,在发生这种情况的情况下,Bar() 与测试位于不同的模块中。我已更新代码以反射(reflect)这一点。

UPDATE-3:如果我创建一个名为 SomeClassToBeMocked 的接口(interface)并将原始类重命名为 SomeClassToBeMockedImpl,一切都会变得非常顺利。但是,我仍然想弄清楚为什么会发生这种情况以及如何避免为此创建接口(interface)。

最佳答案

为了使用 Mockito 模拟函数的返回值,您需要使用 open 关键字对其进行标记:

open class SomeClassToBeMocked @Inject constructor() {
    open fun map(foo: Foo): Bar {...}
}

问题是 Mockito 无法模拟最终(无法覆盖)函数。与 Java 不同,Kotlin 需要对可重写成员进行显式注释。

关于java - 为什么 $MockitoMock$ 实例没有被识别为模拟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48154580/

相关文章:

java - Doc4j pptx查找并替换表格行

Java - 不使用列表搜索文件

java - 在 adobe cq6 实例中使用放心框架运行单元测试用例

android - 如何从 JSON 文件中获取数据?

java - 使用 Gson 填充 Kotlin 数据类

java - stud.java :112: case, 默认值,或 '}' 预期 case1 :System. out.println ("enter name,rollno and percenta ge");

Java clone() 浅拷贝

c# - 为什么或如何将 NUnit 方法与 ICollection<T> 一起使用

c# - FakeItEasy,从子类伪造一个父虚方法

jvm - 非常神秘的运行时错误: Bad type operand on stack