其中一个遗留测试使用Mockito argThat
在循环中存根对应的结果。
如果我将迭代次数减少到1(numberOfItems = 1
,即如果没有循环),则通过。
当它到达第二次迭代时,它会用NPE出错:
java.lang.NullPointerException: Cannot invoke "getValue()" because "arg" is null
字符串
代码如下:
@Test
public void testMy() {
int numberOfItems = 2;
List<MyData> myDataList = getTestData(numberOfItems);
for (MyData md : myDataList) {
when(mockedService.someMethod(
argThat(arg -> Objects.equals(arg.getValue(), md.getMyValue())))) // NPE here on arg.getValue()
.thenReturn(getExpectedResult(md.getMyValue()));
}
List<MyData> resData = testService.methodUnderTest(myDataList);
// assert... resData list has all the expected items and values
}
型
正在测试的方法类似于以下内容
public List<MyData> methodUnderTest(List<MyData> myDataList) {
myDataList.forEach(myData -> {
// ... some logic ...
myData.setResult(mockedService.someMethod(new MyRequest(myData.getMyValue())));
}
});
return myDataList;
}
型
但是对于错误情况,方法调用甚至没有到达,因为NPE在单元测试代码中发生得更早。
最初它是通过被使用有点像这样
when(mockedService.someMethod(
argThat(hasProperty("value", equalTo(md.getMyValue())))))
.thenReturn(getExpectedResult(md.getMyValue()));
型
然而,我看到了一个建议,更喜欢直接比较对象,所以我试图按照建议重写编译,摆脱那些equalTo
和hasProperty
,bot现在进入了那些NPE错误:)
有什么建议我做错了吗?谢谢!!
2条答案
按热度按时间sd2nnvve1#
当你第一次调用
when(mockedService.someMethod(argThat(arg -> Objects.equals(arg.getValue(), md.getMyValue())))).thenReturn(getExpectedResult(md.getMyValue()));
时,这个方法被存根化。当你第二次调用它时,现有的存根试图匹配第二次的存根化调用。argThat
(和所有其他匹配器方法)返回null
,这使得你现有的存根的匹配器抛出。两种可能的解决方案:
argThat(arg -> arg != null && ...)
以不匹配空输入when(mock.call(argThat(...))).thenReturn(result)
形式--它实际上调用了方法!--,而要切换到doReturn(result).when(mock).call(argThat(...))
mfuanj7w2#
从另一端解决了这个问题。
长话短说,这一切都是在我升级到Java 17和Mockito到5.3.1之后开始的,这使得
argThat
与hamcresthasProperty
不兼容,因为这些Matcher
/ArgumentMatcher
不兼容(https://stackoverflow.com/a/8351055/2518705)。在这一点上,我决定取代那些火腿匹配和面对NPE。
现在我意识到,我可以通过使用
org.mockito.hamcrest.MockitoHamcrest.argThat
而不是org.mockito.ArgumentMatchers.argThat
来使它工作。同时,原始问题可能仍然有单独的正确答案:)