【问题标题】:Is there any way to make never() + startsWith() matcher report what matched?有没有办法让 never() + startsWith() 匹配器报告匹配的内容?
【发布时间】:2026-01-12 12:45:01
【问题描述】:

我有这个:

verify(logger, never()).info(startsWith("Created content from "));

错误信息是这样的:

org.mockito.exceptions.verification.NeverWantedButInvoked: 
logger.info(
    startsWith("Created content from ")
);

因为我使用的是startsWith,所以查看完整字符串能够调试此故障会非常有帮助。有没有办法得到那个字符串?

【问题讨论】:

  • 你有很多以"Created content from "开头的日志消息吗?
  • 不确定确切地你在问什么/为什么问。这个问题的答案是取决于程序运行多长时间。每次创建某个对象时,都会记录该消息。它可以在一次测试中发生多次。我会说大约 3 可能是平均水平。
  • 没关系。 Mockito 不会用相应的堆栈跟踪元素记录"But invoked here: ..." 吗?我猜你想要剩下的信息。
  • @SotiriosDelimanolis 是的,但不幸的是,这在这种情况下并不是很有用。很多路径都通向这个地方,它是如何到达那里的,信息量不是很大。在这种情况下调试的关键是知道传入了什么,而不是堆栈跟踪。
  • 我本来打算建议一个ArgumentCaptor,但never() 的检查发生在ArgumentCaptor 有机会收到参数之前。

标签: java mockito hamcrest


【解决方案1】:

我认为你能做到这一点的唯一方法是编写你自己的匹配器。您可以在自己的实用程序类中添加一个返回匹配器的方法,例如...

public class CustomMatchers {
    public static String capturingStartsWith(final String expected) {
        return Mockito.argThat(new TypeSafeMatcher<String>() {

            private String actual;

            @Override
            public void describeTo(Description description) {
                description.appendText("String that starts with: ");
                description.appendValue(expected);
                description.appendText(" actual: ");
                description.appendValue(actual);
            }

            @Override
            protected boolean matchesSafely(String actual) {
                this.actual = actual;
                return actual.startsWith(expected);
            }
        });
    }
}

那么你的测试...

import static CustomMatchers.*;
...
@Test
public void shouldNotDoWhatItDoesNow() {
    classUnderTest.doStuff();

    verify(logger, never()).info(capturingStartsWith("Created content from"));
}

这会给你这样的输出......

org.mockito.exceptions.verification.NeverWantedButInvoked: 
logger.info(
    Start that starts with: "Created content from" actual: "Created content from [WIBBLE]"
);
Never wanted here:
-> at  CustomStartsWithTest.shouldNotDoWhatItDoesNow(CustomStartsWithTest.java:28)
But invoked here:
-> at CustomStartsWith.doStuff(CustomStartsWith.java:12)

(不将类型安全匹配器包装在辅助方法中的“argThat”中并返回匹配器可能更优雅)

我不知道有任何免费库有这样的额外匹配器。可能有一种更聪明的方法可以破解 Mockito 来为您执行此操作...

【讨论】:

    最近更新 更多