Java 使用Mockito模拟方法行为时按任意顺序匹配列表
我有一个使用Mockito的测试,它有一个非常奇怪的行为:它在调试中工作,但在正常运行时失败。经过一些调查,我意识到这是因为我在模仿方法行为,传递一个要匹配的元素列表。但是由于某些原因,列表中的顺序并不总是相同的,因此它不匹配,并且我希望我的mock返回的结果也没有返回,因为这两个列表不是“相等”的Java 使用Mockito模拟方法行为时按任意顺序匹配列表,java,unit-testing,mockito,Java,Unit Testing,Mockito,我有一个使用Mockito的测试,它有一个非常奇怪的行为:它在调试中工作,但在正常运行时失败。经过一些调查,我意识到这是因为我在模仿方法行为,传递一个要匹配的元素列表。但是由于某些原因,列表中的顺序并不总是相同的,因此它不匹配,并且我希望我的mock返回的结果也没有返回,因为这两个列表不是“相等”的 在我的例子中,匹配元素的顺序并不重要。那么,在配置mock时,我如何指定它呢 其实很简单。我们需要一个定制匹配器: import org.apache.commons.collections.Col
在我的例子中,匹配元素的顺序并不重要。那么,在配置mock时,我如何指定它呢 其实很简单。我们需要一个定制匹配器:
import org.apache.commons.collections.CollectionUtils;
import org.mockito.ArgumentMatcher;
import java.util.List;
import static org.mockito.Matchers.argThat;
public class InAnyOrderListMatcher extends ArgumentMatcher<List> {
private final List expected;
public InAnyOrderListMatcher(List expected){
this.expected=expected;
}
@Override
public boolean matches(Object actual) {
if(actual instanceof List){
List actualList=(List)actual;
return CollectionUtils.isEqualCollection(expected,actualList);
}
return false;
}
public static List inAnyOrderListMatcherEq(List expected) {
return argThat(new InAnyOrderListMatcher(expected));
}
}
这是一条单行线。使用Hamcrest
containsInAnyOrder
matcher
when(myMock.myMethod(argThat(containsInAnyOrder(IN_PROGRESS, ABANDONED, EXPIRED))))
.thenReturn(myValue);
为Mockito和Java8的更新版本添加答案
when(
mock.method(argThat(t -> t.containsAll(Arrays.asList(IN_PROGRESS, ABANDONED, EXPIRED))))
).thenReturn(myValue);
如果顺序无关紧要,请将StatusCalculator服务更改为接受集合而不是集合。那么无论顺序如何,equals都将返回true
修复API比在单元测试中绕过它要好。不要重新发明轮子。汉克雷斯特已经有了一个匹配者。看我的答案。是的,你是对的。。但需要注意的是,在大多数情况下,通过该方法将argThat的输出转换为预期类型似乎是强制性的。如果我没有Hamcrest,只有mockito?我不认为这是最佳解决方案,但我通过给出多个when语句绕过了这个问题。如果您只是想通过测试,那么这可能是最简单的方法(如果您的收藏中有少量项目)!
when(myMock.myMethod(argThat(containsInAnyOrder(IN_PROGRESS, ABANDONED, EXPIRED))))
.thenReturn(myValue);
when(
mock.method(argThat(t -> t.containsAll(Arrays.asList(IN_PROGRESS, ABANDONED, EXPIRED))))
).thenReturn(myValue);