如何否定 Mockito 中的 ArgumentMatcher?

eri*_*icj 6 mocking mockito

我创建了一个ArgumentMatcher

private class IsListOf2Elements implements ArgumentMatcher<List<String>>{
    @Override
    public boolean matches(List<String> argument) {
        return ((List<String>)argument).size()==2;
    }
}
Run Code Online (Sandbox Code Playgroud)

我想否定这个匹配,所以当大小不是 2 时匹配,

Mockito.doReturn(false).when(mock).addAll(Mockito.argThat(AdditionalMatchers.not(new IsListOf2Elements())));
Run Code Online (Sandbox Code Playgroud)

但这是不正确的。我明白了,

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
No matchers found for additional matcher Not(?)
-> at my.test.own.Mockito_aTest.test4e(Mockito_aTest.java:136)
Run Code Online (Sandbox Code Playgroud)

Jef*_*ica 6

作为参考,请注意Hamcrest 匹配器和 Mockito 匹配器的行为非常不同。Hamcrest 的无状态 Matcher 对象将 match 函数表示为一个实例,并且可以包装以反转它们的结果;Mockito 的“注册匹配器”仅通过副作用起作用。

argThat将 Hamcrest 匹配器改编为 Mockito 匹配器,Hamcrest 的CoreMatchers.not反转 Hamcrest 匹配器,而 Mockito 的AdditionalMatchers.not反转 Mockito 匹配器(通过副作用)。这是CoreMatchers.not总是返回 a Matcher<T>,而AddionalMatchers.not返回任意T; 的部分原因。它在你看不到的 Mockito 状态下运行。

这为您提供了以下行为:

// BAD: Don't use AdditionalMatchers to invert a Hamcrest matcher.
doReturn(false).when(mock).addAll(
    Mockito.argThat(AdditionalMatchers.not(new IsListOf2Elements())));

// GOOD: Use AdditionalMatchers to invert a Mockito matcher. (See ericj's answer.)
doReturn(false).when(mock).addAll(
    AdditionalMatchers?.not(Mockito.argThat??(new IsListOf2Elements())));

// ALSO GOOD: Use CoreMatchers to invert a Hamcrest matcher. (See troig's answer.)
doReturn(false).when(mock).addAll(
    Mockito.argThat??(CoreMatchers.not(new IsListOf2Elements())));
Run Code Online (Sandbox Code Playgroud)

如果您创建的异常与存根行为有关,那么除了特定异常之外,您还可以使用更具体的覆盖来存根一般行为。


tro*_*oig 2

似乎您不能使用自定义匹配器作为AdditionalMatchers.not方法参数。

但是,您可以使用 hamcrest org.hamcrest.CoreMatchers代替。这应该有效:

Mockito.doReturn(false).when(mock).addAll(Mockito.argThat(CoreMatchers.not(new IsListOf2Elements())));
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你