Mockito Mock a method call called twice
我试图用mockito来模拟一个方法。 但是我注入模拟的类在调用两个相同类型的不同对象时调用该方法两次,但是根据对象中的值确定方法的输出。
所以,例如,如果我想嘲笑
1 | public ArrayList<example> attemptToMock(testObject testing) |
让sat类型
因此,如果testObject中的字符串值为"OK",那么
如何编写一个测试来处理一个调用,以便一个类可以在同一个方法中调用
一些选择:
-
覆盖对象上的
equals 和hashCode (TestObject)。这只有在对象上的所有值都是可预测的情况下才可行,并且可能比其他解决方案更有效,但如果您还需要编写equals 和hashCode (例如,对于Map和Set行为),这是合理的解决方案。1
2
3// Mockito compares with objects' equals(Object) methods by default.
when(collaborator.attemptToMock(object1)).thenReturn(array1);
when(collaborator.attemptToMock(object2)).thenReturn(array2); -
写一个Hamcrest匹配器并使用它匹配数组。对于特定情况,这可以作为
equals 的紧凑模拟,如果您需要在许多测试中根据相同的值更改行为,则特别方便。1
2
3
4
5
6
7
8
9
10
11
12
13public class IsATestObjectWithValue extends TypeSafeMatcher<TestObject> {
private final String expectedValue;
public IsATestObjectWithValue(String expectedValue) {
super(TestObject.class);
this.expectedValue = expectedValue;
}
@Override public void matchesSafely(TestObject object) {
// object will never be null, but object.value might.
return expectedValue.equals(object.value);
}
}现在您可以编写如上所述的等效匹配:
1
2
3
4when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("OK")))
.thenReturn(array1);
when(collaborator.attemptToMock(argThat(new IsATestObjectWithValue("NO")))
.thenReturn(array2); -
使用答案,如wdf所述。匿名内部答案很常见且非常简洁,您可以访问所有参数。这对于一次性解决方案尤其有用,或者如果您希望在传入无效值(testObject.value)时显式地立即使测试失败。
-
作为最后的手段,如果调用的顺序是可预测的,您可以按顺序返回多个值。
1
2
3
4when(collaborator.attemptToMock(any(TestObject.class)))
.thenReturn(array1).thenReturn(array2);
when(collaborator.attemptToMock(any(TestObject.class)))
.thenReturn(array1, array2); // equivalent无论参数如何,上述任何一行都将返回第一次调用的
array1 和第二次调用的array2 以及之后的所有调用。这个解决方案比原始问题要脆弱得多 - 如果调用顺序发生变化,或者如果其中一个调用被删除或重复,它将失败 - 但如果测试非常紧凑,有时候这是最紧凑的解决方案临时或如果订单是绝对修复的。
您可以访问传递给模拟方法调用的参数,并使用Answer接口相应地改变返回值。请参阅此问题的答案以及答案的文档。
基本上,这里唯一的奇怪/非显而易见的事情是你必须将参数向下转换为你期望的类型。因此,在您的情况下,如果您正在模拟一个采用单个"TestObject"参数的方法,那么您必须在"回答"实现中执行类似的操作:
1 2 3 4 5 6 7 |