我有一段看起来像这样的代码:
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);
}
然后我的代码正确地抛出一个空指针异常。
我的测试的第一版和第二版有什么区别?
在我的第一个版本中,我告诉ockA返回模仿B。但是我也将mockB设置为null,所以当调用b.doSomething()时,我认为该方法应该抛出一个null指针,因为它试图调用null.doSomething()。
我知道我要测试的行为应该使用第二个版本,但是我不知道为什么第一个版本具有不同的行为。
答案 0 :(得分:2)
使用:
when(mockA.getB()).thenReturn(mockB);
...
mockB = null;
thenReturn
设置模拟以返回在那一刻(即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
的设置,因为这些操作不会更改地址该对象在内存中的大小。
答案 1 :(得分:0)
在第一个测试用例中,您正在模拟一个虚拟对象,因此mocikto不会向您报告null。
在第二个测试用例中,您将代码明确返回null。