是否可以在使用非预定义参数调用模拟时抛出异常?有Answers.RETURNS_SMART_NULLS
,但它并不是我真正需要的,因为如果null
是合法的返回值(不会导致NullPointerException
,而是导致错误,则它不起作用)上。
编辑:一些背景。因此,在定义模拟时,在Mockito中,您可以为每个调用指定返回值,如下所示:
when(myMock.someMethod(arg1, arg2)).thenReturn(returnValue);
当使用参数调用myMock.someMethod
时,我没有在测试中给出返回值,它只返回null
。我想将它配置为立即崩溃并告诉我,我忘了为某些参数组合定义返回值。
编辑2:有人建议提供一个自定义defaultAnswer
,在调用时会抛出异常。不幸的是,这不起作用。即使存在模拟,也会调用默认答案'answer()
方法。这是一个示例:
public class Test {
public static class Adder {
public int add(int a, int b) {
return a + b;
}
}
public static final Answer<Object> THROW_ON_UNDEFINED_ARGS = new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
throw new IllegalArgumentException(
String.format("Calling a mock with undefined arguments: %s %s",
invocation.getMethod(),
Arrays.toString(invocation.getArguments())));
}
};
public static void main(String[] args) {
Adder adderMock = mock(Adder.class, THROW_ON_UNDEFINED_ARGS);
when(adderMock.add(2, 3)).thenReturn(5);
System.out.println(adderMock.add(2, 3));
}
}
即使定义了adderMock.add(2, 3)
,也会抛出异常。
答案 0 :(得分:8)
你可以在模拟的构造中提供一个默认的Answer
,它总是抛出一个异常。然后每个被存根的电话都会像往常一样。这些路径之外的所有东西都会抛出异常。像这样:
final String arg = "some arg";
Collection<Object> object = mock(Collection.class, new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
throw new IllegalArgumentException("You cannot invoke " + invocation.getMethod() +
" with " + Arrays.toString(invocation.getArguments()));
}
});
doReturn(true).when(object).add(arg);
object.add(arg); // Goes ok
object.add("azertyuiop"); // Throws the exception
答案 1 :(得分:3)
首先,有点“好工程”嘟?? - 你为什么要这样做? Mockito试图'推广'BDD风格 - 你设置(模拟)你的调用,你执行代码并验证交互完全符合你的预期,而不是'它没有调用任何其他' - 你试图做一些描述的东西Finding irrelevant invocation? 一般来说,如果我想模仿所有案例,只需要一个 - 这让我自问我的测试是否真的很好。
无论如何,关于主题:)
在Mockito中,您可以使用不同的值定义多个when
,例如
class Foo {
public String bar(int a) {
return "bar = " + a;
}
}
Mockito.when(task.bar(Matchers.anyInt())).thenReturn("L")
Mockito.when(task.bar(3)).thenThrow(new IllegalAccessError())
task.bar(4); // returns "L"
task.bar(3); //throws IllegalAccessError
请注意,when
的顺序很重要。规则以相反的顺序处理(或者更改为覆盖实际的匹配器)。
在我的代码中,我们首先模拟anyInt,然后是3 - 它可以工作。如果你反转它 - 对bar()
的两次调用都会返回'L'。
答案 2 :(得分:1)
只需指出另一种方法,即使用thenAnswer
:
when(myMock.someMethod(anyString(), anyString())).
thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String arg1 = (String) args[0];
String arg2 = (String) args[1];
if ("arg1".equals(arg1) && "arg2".equals(arg2)) return "someValue";
throw new Exception();
}
});
myMock.someMethod("arg1", "arg2"); // Returns "someValue"
myMock.someMethod("xxx", "yyy"); // Throws Exception
希望它有所帮助。