我想在单个方法中使用两个自定义匹配器。基本上,如果我传递方法VALUE_A,我希望它返回RESULT_A,如果我将它传递给VALUE_B,我希望它返回RESULT_B。所以这是一段代码摘录:
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
//When this happens, the value of the get argument is null, so this method throws an NPE
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
class IsEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)));
}
}
[...]
//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);
[...]
//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);
当我将IsEmpty自定义匹配器分配给mockHTable.get()方法时,它调用IsNonEmpty.matches()函数。不知道为什么会这样做。所以我将IsNonEmpty类更改为:
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher. Weird, no?
if(get == null) {
return false;
}
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
然后一切正常!当我将IsEmpty匹配器分配给mockHTable.get()函数时仍然会调用IsNonEmpty.matches(),但是我的匹配器确实可以正常工作。
那是什么交易?为什么会这样?我的解决方案是否足以弥补这种奇怪的行为,或者我做错了吗?
答案 0 :(得分:11)
在第二行存根上调用IsNonEmpty.matches()
的原因是Mockito.argThat(new IsEmpty())
返回null,然后传递给mockHTable.get()
。必须根据之前的存根检查此调用,以查看它是否匹配;这意味着要调用IsNonEmpty.matches()
。
我不确定为什么这会让你的测试失败 - 如果没有看到所有的代码就很难分辨。
但是,每当你不得不多次存根同一个模拟时,我会认真地建议使用doReturn...when
而不是when...thenReturn
。如果你这样做,你不会遇到这样的问题。事实上,我更倾向于doReturn...when
优先使用when...thenReturn
(同样doThrow
和doAnswer
),尽管大多数人更喜欢when...thenReturn
。
使用doReturn...when
语法重写一条存根线如下所示。另一个是相似的。
Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));
最后,代表Mockito开发团队(我是其中的一员)的请求。如果您认为Mockito中存在错误 - 并且根据您的描述,我认为可能存在 - 请使用
对于Mockito团队来说,如果你能够真正发布一个完整的例子,而不仅仅是你认为的关键线是有用的 - 有时Mockito问题的原因是在一个意想不到的地方。