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