Java 为什么不';t null模拟对象抛出NullPointerException?
我有一段代码如下所示:Java 为什么不';t null模拟对象抛出NullPointerException?,java,unit-testing,mockito,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吗 当我
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指针,因为它试图调用null.doSomething()
我知道我应该使用第二个版本来测试我试图测试的行为,但我不知道为什么第一个版本有不同的行为。使用:
when(mockA.getB()).thenReturn(mockB);
...
mockB = null;
thenReturn
将mock设置为返回mockB当时持有的值(即,执行时…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(mockB.getName()).thenReturn("fred");
when(mockA.getB()).thenReturn(mockB);
when(mockB.getAge()).thenReturn(23);
...
mockB = null
when(mockA.getB())
的定位不影响(也不受)mock对象的getName
和getAge
的设置,因为这些操作不会更改该对象在内存中的地址。
when(mockA.getB()).thenReturn(mockB);
...
mockB = null;
thenReturn
将mock设置为返回mockB当时持有的值(即,执行时…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(mockB.getName()).thenReturn("fred");
when(mockA.getB()).thenReturn(mockB);
when(mockB.getAge()).thenReturn(23);
...
mockB = null
(mockA.getB())时
的定位不影响(也不受)模拟对象getName
和getAge
的设置,因为这些操作不会更改内存中该对象的地址。在第一个测试用例中,您模拟的是一个虚拟对象,所以mocikto不会向你报告mockB的空值
在第二个测试用例中,您显式地将代码设置为返回null。在第一个测试用例中,您模拟的是一个虚拟对象,因此mocikto不会将mockB的值报告为null
在第二个测试用例中,您显式地将代码设置为返回null。wow,感谢您提供的字符串示例。这真的让事情有了正确的角度。。。我的印象是,既然thenReturn
引用的是一个对象,那么我放置when…then
s的顺序就无关紧要了。。。虽然我仍然认为第一种方法更直观,但它有帮助;我刚刚在答案中添加了(希望)澄清发生了什么,因此有了正确的想法,它会变得更直观。哇,感谢字符串示例。这真的让事情有了正确的角度。。。我的印象是,既然thenReturn
引用的是一个对象,那么我放置when…then
s的顺序就无关紧要了。。。虽然我仍然认为第一种方法更直观,但它有帮助;我刚刚补充了答案(希望)来澄清发生了什么,所以有了正确的想法,它会变得更直观。