13

我正在为一个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.
    }
}

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

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.
        }
    }
}

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

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

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

  1. 我是否正确地接近了这个测试设置?或者有没有更好的、Mockito 推荐的、在后台doBuzz调用的测试方法doWidget?和
  2. 我可以做些什么来模拟/存根doWidget,因为它是我整个FizzConfigurator班级中最关键的方法?
4

4 回答 4

28

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

这是我的做法:

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);
于 2013-02-04T15:55:55.413 回答
0

这清楚地表明doWidget方法应该属于另一个FizzConfigurator依赖的类。

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

于 2014-03-31T00:55:22.133 回答
0

就我而言,对于我试图存根的方法,我传入了不正确的匹配器。

我的方法签名(对于我试图存根的超类方法):字符串,对象。

我正在传递:

myMethod("string", Mockito.nullable(ClassType.class))并得到:

Hints: 1. missing thenReturn() 2. you are trying to stub a final method, which is not supported 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

在另一个参数中使用匹配器时,我们还需要为字符串使用一个:

myMethod(eq("string"), Mockito.nullable(ClassType.class))

希望这可以帮助!

于 2018-07-25T13:56:06.127 回答
0

这不是问题的直接答案,但我在尝试解决我的问题时遇到了它,并且此后没有找到更相关的问题。

如果您尝试存根/模拟标记为 Spy 的对象,则 Mockito 仅在使用do...whenJB Nizet 暗示的约定创建存根时才会选择存根:

doReturn(Set.of(...)).when(mySpy).getSomething(...);

它没有被以下人员拾取:

when(mySpy.getSomething(...)).thenReturn(Set.of(...));

与中的评论相匹配MockHandlerImpl::handle

// stubbing voids with doThrow() or doAnswer() style
于 2021-05-28T07:36:26.847 回答