我有一段代码,如下所示:
public void someMethod(ObjectA a) {
ObjectB b = a.getB();
b.doSomething();
}
我的测试是:
@Test
public void someTest_1() {
when(mockA.getB()).thenReturn(mockB);
...
mockB = null;
someMethod(mockA);
}
上面的代码不应该抛出 NPE 吗?
当我将测试更改为:
@Test
public void someTest_2() {
when(mockA.getB()).thenReturn(null);
someMethod(mockA);
}
然后我的代码正确地抛出空指针异常。
我的测试的第一个版本和第二个版本有什么区别?
在我的第一个版本中,我告诉mockA 返回mockB。但我也将mockB设置为null,因此当调用b.doSomething()时,我认为该方法应该抛出一个空指针,因为它试图调用null.doSomething()。
我知道我应该使用第二个版本来实现我想要测试的行为,但我不知道为什么第一个版本有不同的行为。
最佳答案
与:
when(mockA.getB()).thenReturn(mockB);
...
mockB = null;
thenReturn
设置mock以返回mockB在那一刻(即执行when ... thenReturn
的那一刻)所持有的值,无论mockB随后发生什么。
这与字符串的行为方式没有太大不同:
String s1 = "abc";
String s2 = s1;
s1 = "xyz";
这里的结果是 s2 仍然具有值“abc”,因为这是分配时的值,无论 s1 随后发生什么。
编辑:
考虑这个问题的方法是像 mockB
这样的变量, s1
和s2
是“引用”(又名“指针”)变量 - 也就是说,它们的值指向目标对象内存中的地址。
何时 thenReturn(mockB)
或s2 = s1
被执行,它是mockB
的值和s1
正在传递或复制 - 即目标对象或字符串的地址(不是变量 mockB
或 s1
本身的地址)。这就是变量mockB
的值随后发生变化的原因。或s1
本身没有任何影响。
when ... then
的定位在哪里对对象本身执行的操作没有影响 - 例如:
when(mockB.getName()).thenReturn("fred");
when(mockA.getB()).thenReturn(mockB);
when(mockB.getAge()).thenReturn(23);
...
mockB = null
when(mockA.getB())
的定位不影响(并且不受)getName
的设置和getAge
模拟对象的地址,因为这些操作不会更改该对象在内存中的地址。
关于java - 为什么 null Mock 对象不会抛出 NullPointerException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59853559/