我正在使用Mockito进行单元测试。我需要模拟一个填充一些输入的void方法。非常天真的例子:
class Something {
AnotherThing thing = new AnotherThing();
public int doSomething(Stuff stuff)
{
thing.doThing(stuff);
if(thing.getName().equals("yes")){
return 1;
}
else {
return 2;
}
}
}
class AnotherThing() {
public void doThing(Stuff stuff){
if(stuff.getName().equals("Tom")) {
stuff.setName("yes");
}
else {
stuff.setName("no");
}
}
}
class Stuff()
{
String name;
// name getters and setters here
}
在这种情况下,我将尝试模拟AnotherThing
来测试Something
。
但是,我在测试的类中多次调用这个void方法。我每次调用它都需要不同的"Answer
"。我的意思是,每次调用它时,我都想调用void方法来做不同的事情。
我查阅了API,但找不到解决方案。这对Mockito来说可能吗?
您需要的是一个Mockito Answer
对象。这是一个包含少量功能的对象,当调用mock的方法时可以运行这些功能。查看doAnswer
的Mockito文档以了解更多详细信息;但基本上你想要的是这样的东西。
doAnswer(new Answer<Object>(){
@Override
public Object answer(InvocationOnMock invocation){
Object[] arguments = invocation.getArguments();
Stuff argument = (Stuff) arguments[0];
if(stuff.getName().equals("Tom")) {
stuff.setName("yes");
}
else {
stuff.setName("no");
}
return null;
}
}).when(mockObject).doThing(any(Stuff.class));
有一种更简单的方法:
doNothing().doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();
通过这种方式,对该方法的多次调用可以做不同的事情。
Mockito为您提供了一种截取连续调用的可能性。我想这正是你需要的。这里有一个链接到mockito文档中的必要部分。
你可以这样写:
Mockito.when(mockAnotherThing.doThing(stuff)).thenReturn("yes").thenReturn("no");
在此之后,mockito在第一次调用时将返回"yes",在第二次调用时返回"no"。
顺便说一句,我认为你需要像这样修改你的示例代码(在其他情况下,它不会起作用):
class AnotherThing() {
public String doThing(Stuff stuff){
if(stuff.getName().equals("Tom")) {
return "yes";
}
else {
return "no";
}
}
}
您不能使用equals,因为返回类型为void,或者将doThing()的返回类型更改为String,然后像这样模拟
Anotherthing anotherthing = mock(Anotherthing.class)
when(anotherThing.doThing(isA(Stuff.class))).thenReturn("yes").thenReturn("no");
您可能需要多次对此进行模拟,否则将在连续2次调用后返回最后一个存根值("no");
为什么需要不同的Answer
?你可以使用同一个:
doAnswer(new Answer<Object>(){
private int call;
@Override
public Object answer(InvocationOnMock invocation){
...
call = call + 1;
if (call % 2 == 0) {
//do something
} else {
//another behavior
}
}
}).when(mockObject).doThing(any(Stuff.class));