使用Mockito模拟方法行为时,按任何顺序匹配列表



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

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

在我的情况下,要匹配的元素顺序无关紧要。那么,在配置模拟时,该如何指定呢?

添加了Mockito和Java 8

的新版本的答案
when(
   mock.method(argThat(t -> t.containsAll(Arrays.asList(IN_PROGRESS, ABANDONED, EXPIRED))))
).thenReturn(myValue);

如果您在版本2.1.0之前有摩擦脚:

使用hamcrest containsInAnyOrder匹配器。

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

谢谢@kolobok指出的是,从Mockito 2.1.0(我写了这个答案之后出现),这不再有效。

因此,版本2.1.0及以上:

添加对Hamcrest的依赖性,并使用MockitoHamcrest.argThat代替Mockito.argThat

使用Mockito 2.1.0的破坏变化的更多详细信息在https://www.javadoc.io/doc/org.mockito/mockito/mockito-core/2.1.0/org/org/mockito/mockito/argumentMather.argumentMather.htmather.htmather.html

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

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

如果订单无关紧要,请更改您的状态计算器服务以接受集合而不是集合。然后,无论秩序如何,平等将返回真实。

修复API比在单元测试中围绕它进行入侵更好。

相关内容

  • 没有找到相关文章

最新更新