用Mockito嘲笑间谍方法

2022-09-03 18:18:57

我正在为一个类编写一个单元测试,如下所示:FizzConfigurator

public class FizzConfigurator {
    public void doFoo(String msg) {
        doWidget(msg, Config.ALWAYS);
    }

    public void doBar(String msg) {
        doWidget(msg, Config.NEVER);
    }

    public void doBuzz(String msg) {
        doWidget(msg, Config.SOMETIMES);
    }

    public void doWidget(String msg, Config cfg) {
        // Does a bunch of stuff and hits a database.
    }
}

我想写一个简单的单元测试来存根方法(这样它实际上就不会触发并命中数据库),但这允许我验证调用最终是否执行。Mockito似乎是这里工作的正确工具。doWidget(String,Config)doBuzz(String)doWidget

public class FizzConfiguratorTest {
    @Test
    public void callingDoBuzzAlsoCallsDoWidget() {
        FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
        Mockito.when(fixture.doWidget(Mockito.anyString(), Config.ALWAYS)).
            thenThrow(new RuntimeException());

        try {
            fixture.doBuzz("This should throw.");

            // We should never get here. Calling doBuzz should invoke our
            // stubbed doWidget, which throws an exception.
            Assert.fail();
        } catch(RuntimeException rte) {
            return; // Test passed.
        }
    }
}

这似乎是一个很好的游戏计划(至少对我来说)。但是当我实际编写代码时,我在测试方法(该行)中的第二行上收到以下编译器错误:Mockito.when(...)

类型 Mockito 中的 when(T) 方法不适用于参数 (void)

我看到Mockito无法模拟返回的方法。所以我问:void

  1. 我是否正确接近此测试设置?还是有更好的,Mockito推荐的测试方式,可以在引擎盖下调用?和doBuzzdoWidget
  2. 我能做些什么来嘲笑/存根,因为它是我整个班级中最关键的方法?doWidgetFizzConfigurator

答案 1

我不会使用异常来测试它,而是使用验证。另一个问题是,你不能使用返回void的方法。when()

以下是我的做法:

FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
doNothing().when(fixture).doWidget(Mockito.anyString(), Mockito.<Config>any()));
fixture.doBuzz("some string");
Mockito.verify(fixture).doWidget("some string", Config.SOMETIMES);

答案 2

这是一个明确的迹象,表明方法应该属于另一个将依赖的类。doWidgetFizzConfigurator

在测试中,此新依赖项将是一个模拟,您可以轻松验证其方法是否使用 调用。verify


推荐