使用Mockito模拟方法行为时以任何顺序匹配List

时间:2016-11-30 08:57:37

标签: java unit-testing mockito

我使用Mockito进行测试时有一个非常奇怪的行为:它在调试中工作但在正常运行时失败。经过一番调查后,我意识到这是因为我在嘲笑方法行为,传递一系列要匹配的元素。但由于某种原因,列表中的顺序并不总是相同,所以它不匹配,我不希望我的模拟返回,因为2个列表不是"等于"

 when(mockStatusCalculatorService.calculateStatus(Arrays.asList(IN_PROGRESS, ABANDONNED,EXPIRED))).thenReturn(ConsolidatedStatus.EXPIRED);

就我而言,要匹配的元素顺序并不重要。那么在配置我的模拟时如何指定呢?

4 个答案:

答案 0 :(得分:6)

这是一个单行。使用Hamcrest containsInAnyOrder匹配器。

when(myMock.myMethod(argThat(containsInAnyOrder(IN_PROGRESS, ABANDONED, EXPIRED))))
    .thenReturn(myValue);

答案 1 :(得分:4)

为较新版本的Mockito和Java 8添加答案

when(
   mock.method(argThat(t -> t.containsAll(Arrays.asList(IN_PROGRESS, ABANDONED, EXPIRED))))
).thenReturn(myValue);

答案 2 :(得分:1)

实际上它非常简单。我们需要一个自定义匹配器:

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));
}

}

然后在测试中调用它:

when(mockStatusCalculatorService.calculateStatus( inAnyOrderListMatcherEq(Arrays.asList(IN_PROGRESS, ABANDONNED,EXPIRED)))).thenReturn(ConsolidatedStatus.EXPIRED);

答案 3 :(得分:0)

如果顺序无关紧要,请更改StatusCalculator服务以接受Set而不是Collection。然后,无论顺序如何,equals都将返回true。

比在单元测试中破解它更能修复您的API。