为什么不为null的Mock对象抛出NullPointerException?

时间:2020-01-22 06:07:54

标签: java unit-testing mockito

我有一段看起来像这样的代码:

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()。

我知道我要测试的行为应该使用第二个版本,但是我不知道为什么第一个版本具有不同的行为。

2 个答案:

答案 0 :(得分:2)

使用:

when(mockA.getB()).thenReturn(mockB);
...
mockB = null;

thenReturn设置模拟以返回在那一刻(即when ... thenReturn被执行的那一刻)mockB所持有的值,而不管随后的嘲笑是什么。

与字符串的行为没什么不同:

String s1 = "abc";
String s2 = s1;
s1 = "xyz";

这里的结果是s2仍然具有值“ abc”,因为这是它被分配的那一刻的值,而不管随后s1发生了什么。

编辑:

对此进行思考的方式是,像mockBs1s2这样的变量是“引用”(也称为“指针”)变量-也就是说,它们的值指向目标对象在内存中的地址。

执行thenReturn(mockB)s2 = s1时,正在传递或复制的是mockBs1- ,即目标对象或字符串的地址(而不是变量mockBs1本身的地址)。这就是为什么随后更改变量mockBs1本身的值不起作用的原因。

when ... then的位置没有影响的地方就是对对象本身执行的操作-例如:

when(mockB.getName()).thenReturn("fred");

when(mockA.getB()).thenReturn(mockB);

when(mockB.getAge()).thenReturn(23);
...
mockB = null

when(mockA.getB())的位置不会影响(也不受其影响)模拟对象的getNamegetAge的设置,因为这些操作不会更改地址该对象在内存中的大小。

答案 1 :(得分:0)

在第一个测试用例中,您正在模拟一个虚拟对象,因此mocikto不会向您报告null。

在第二个测试用例中,您将代码明确返回null。

相关问题