使用“when”作为验证



我有一个在数百次测试中使用的实用方法,用于模拟自定义随机发生器的返回值。这是我的代码的一个(高度人工的)模型:

interface CardRandomiser{
    Card getCard(Suit suit);
}
void mockCard(Suit suit, Face face) {
    CardRandomiser rand = mock(CardRandomiser.class);
    when(rand.getCard(suit)).thenReturn(new Card(suit, face));
    Game.setCardRandomiser(rand);
}

然后可以将其用作:

mockCard(Suit.CLUBS, Face.QUEEN);
Card card = pickACardAnyCard();
assertThat(card.getFace(), is(Face.QUEEN));

然而,这使得一些错误有点难以发现。如果测试中的方法错误地请求Suit.HEARTS,那么mock返回null,断言正确地失败。但是,通过错误消息无法判断传递给mock的是什么。

很明显,我可以用verify来处理这个问题。我可以从mockCard函数中传递mock back,然后分别验证是否使用正确的值调用了is。但这确实混淆了与测试内容无关的测试断言。每次调用此方法时,我都会指定一个预期的参数值,我更愿意将断言放在一个位置。请注意,这一切都发生在调用测试中的方法之前。

理想情况下,如果使用意外值调用when语句,我希望它抛出异常。类似于:

when(rand.getCard(suit)).thenReturn(new Card(suit, face));
when(rand.getCard(intThat(not(is(suit))))).thenThrow(new IllegalArgumentException());

这会起作用,并在调用getCard时停止测试,哪个更好。但它仍然不允许我展示什么是不正确的论点。

我还使用ArgumentCaptor进行了尝试,然后检查捕获的值。但很明显,它们适用于verify语句,而不是when语句。

有没有标准的Mockito方法可以做到这一点,或者我需要用verify语句来打乱我的测试?

您可以使用thenAnswer配置mockito应答,例如

private CardRandomiser mockCard(final Suit suit, final Face face) {
    CardRandomiser rand = mock(CardRandomiser.class);
    when(rand.getCard(any(Suit.class))).thenAnswer(new Answer<Card>() {
        @Override
        public Card answer(InvocationOnMock invocation) throws Throwable {
            if(!suit.equals(invocation.getArguments()[0])) {
                 throw new IllegalArgumentException(
                         String.format("Value %s passed, but mocked for %s", invocation.getArguments()[0], suit));
            }
            return new Card(suit, face);
        }
    });
    return rand;
}

相关内容

  • 没有找到相关文章