java - 为什么这个 Mockito.mock 对象被调用而不是被模拟?

标签 java unit-testing mocking mockito

我正在单元测试我的类并遇到这种情况:我使用 Mockito 模拟一个对象并调用该对象的方法。当我这样做时,我希望不会调用真正的方法,并且程序流程将继续。发生的情况是,正在调用真正的方法,并且我得到了 NullPointerException,因为如果我使用此参数调用该方法,就会发生这种情况。

Mockito.mock 不应该阻止这种行为吗?

Mockito documentationBy default, for all methods that return value, mock returns null, an empty collection or appropriate primitive/primitive wrapper value (e.g: 0, false, ... for int/Integer, boolean/Boolean, ...).this answer证实了我的预期行为 In a mock all methods are stubbed and return "smart return types". This means that calling any method on a mocked class will do nothing unless you specify behaviour.

代码:

public class BrokenTest {
    @Test
    public void shouldPassBecauseItIsMocked() throws IOException {
        Object anyObject = Mockito.mock(Object.class);
        ObjectOutputStream objectOutputStream = Mockito.mock(ObjectOutputStream.class);
        objectOutputStream.writeObject(anyObject);
    }
}

我预计这个测试会通过,但我得到一个 NullPointerException:

java.lang.NullPointerException
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1108)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at packageName.BrokenTest.shouldPassBecauseItIsMocked(BrokenTest.java:14)
    ...

(BrokenTest.java:14实际上是objectOutputStream.writeObject(anyObject);行)

P.S.:我并不是真的想测试ObjectOutputStream但我的一类使用 ObjectOutputStream.writeObject(Object object) 。当我这样做时,问题才真正出现 myObjectWithMockedObjectOutputStream.methodThatCallsWriteObject()

最佳答案

Mockito 不会改变语言的工作方式。方法按照它们在代码中出现的顺序进行调用。 这意味着在像这样的模拟方法的情况下:

when(mockObject.getSomething()).thenReturn(SOMETHING_ELSE);

首先在模拟对象上调用 getSomething() ,然后在将控制权交给测试中的代码之前,mockito 的基础结构会替换返回值。

这意味着如果 getSomething() 调用模拟对象的某些依赖项,则后者不会初始化并导致 NPE。

解决这个问题的方法是使用另一种形式的配置模拟:

doReturn(SOMETHING_ELSE).when(mockObject ) .getSomething();

请注意,when 的右大括号从方法后面移动到 .. 之前

这允许 Mokito 拦截完整的方法调用,这样就不会抛出 NPE。

关于java - 为什么这个 Mockito.mock 对象被调用而不是被模拟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55943150/

相关文章:

c# - mbunit v3 文档

unit-testing - 模拟聚合类

java - 使用 Mockito 模拟静态方法

java - 如何模拟返回文件的方法

java - 向 GUI 添加标签和文本框控件

java - Hibernate:使用executeUpdate()批量删除不会清除一级缓存

java - 在 Spring Boot 中使用 Junit 模拟其他类的对象并返回期望的值

java - 影响 for 循环的出队方法 (Java)

java - 使用 PDFBox 和 Swing 显示嵌入字体

c# - 在 C# 中引发事件的单元测试(按顺序)