在测试场景中测试不改变任何内容的无效方法

Testing void methods that do not change anything in Test scenario

我知道每个不做任何事情的方法都不应该被测试(或者甚至不存在)。问题是,我的方法通常会做一些事情,但对于测试场景,我必须模拟它所做的事情。但我仍然想断言它将发送给外部事物的参数。

听起来比实际更复杂 - 查看我的代码片段以便更好地理解:

class A {
    @Inject
    private Mailer mailer; // Custom mailer class

    public void doSomething() {
        Date date = new Date(); // dynamic parameter I do not care about in the test
        String parameter = "test"; // The parameter I want to test later

        mailer.sendMail(parameter, date);
    }
}

class ATest {
    @Mock
    @Produces
    private Mailer mailer;

    @Inject
    private A classToTest;

    @Test
    public void testDoSomething() throws Exception {

        classToTest.doSomething();

        assertThat(??).isEqualTo("test"); //How can I get the value of parameter?
    }
}

如您所见,我需要模拟我的电子邮件程序,这样我就不会在每次测试运行时都发送电子邮件。

parameter 提升为全局变量是没有意义的。

有什么方法可以在不改变A的代码的情况下测试parameter的值吗?如果不是,最好的解决方案是什么,而不会为了测试而弄乱我的 class?

您需要使用Mockito.verify:

verify(mailer, times(1)).sendMail("test");

Verify 检查您的 mock 发生了什么:一个方法被调用了多少次,以及为该方法提供了哪些参数。


更新: 如果你想排除某些参数,你可以使用 org.mockito.Matchers.any - 更容易将其作为静态导入。 (注意:如果您确实忽略了一些参数,那么您现在要包含的参数必须包含在 org.mockito.Matchers.eq 中)。

verify(mailer, times(1)).sendMail(eq("test"), any(Date.class));

一种方法是使用 可变对象 参数化方法 doSomething,您可以在方法执行时设置该对象并在测试方法中断言。否则,您还可以检查是否为任何负面情况抛出异常,例如

@Test(expected = EmailSendException.class)
public void testDoSomething(){
    ....
}