2

看这个例子:

class Foo { }

class Bar {
    void takeIt(int i, String arg) { System.out.println(arg + i); }
}

public class Mcve {    
    @Test
    public void passes() {
        Foo foo = Mockito.mock(Foo.class);
        Bar bar = Mockito.mock(Bar.class);
        bar.takeIt(42, "surprise: " + foo);
        String substring = "surprise: " + foo;
        Mockito.verify(bar).takeIt(ArgumentMatchers.eq(42),
                ArgumentMatchers.contains(substring));
    }

    @Test
    public void fails() {
        Foo foo = Mockito.mock(Foo.class);
        Bar bar = Mockito.mock(Bar.class);
        bar.takeIt(42, "surprise: " + foo);
        Mockito.verify(bar).takeIt(ArgumentMatchers.eq(42),
                ArgumentMatchers.contains("surprise: " + foo));
    }    
}

这两个测试几乎相同,唯一的区别是:用于contains()匹配器的字符串在 中预先计算passes(),但在 中内联fails()

fails()呕吐:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at com.ibm.hwmca.z.svm.zhyp.managed.Mcve.fails(Mcve.java:43)

This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

For more info see javadoc for Matchers class.


    at java.lang.String.valueOf(String.java:2994)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at Mcve.fails(Mcve.java:43)
...

(显然:错误消息是完全错误的,因为上面的代码对所有参数都使用了匹配器)

更有趣的是:它只会在超过 1 个要匹配的参数时失败(如果一个从 中删除int参数gimme(),并且只是传递/匹配该字符串参数:传递)。

谁能准确解释这里发生了什么,有没有办法做这样的匹配contains("surprise: " + foo),比如foo被 Mockito 嘲笑?


当然,这实际上是指 MCVE。从我们环境中失败的单元测试到这里的这个例子,我花了 3 个小时。

在真实环境中,Bar 类是一个模拟的日志工具。Foo 对象代表一些由一些假持久层创建的“数据实体”。我必须验证生产代码确实记录了特定信息,并且其中一些信息来自伪造的数据对象。

4

0 回答 0