我正在单元测试我的类并遇到这种情况:我使用 Mockito 模拟一个对象并调用该对象的方法。当我这样做时,我希望不会调用真正的方法,并且程序流程将继续。发生的情况是,正在调用真正的方法,并且我得到了 NullPointerException,因为如果我使用此参数调用该方法,就会发生这种情况。
Mockito.mock 不应该阻止这种行为吗?
Mockito documentation说By 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/