我想存根一个存储库类来测试另一个具有存储库的类(Holder类)。存储库接口支持CRUD操作,并且有很多方法,但我对Holder类的单元测试只需要调用其中的两个。存储库接口:
public interface IRepo {
public void remove(String... sarr);
public void add(String... sarr);
//Lots of other methods I don't need now
}
我想创建一个存储库模拟,它可以存储实例,仅为add
和remove
定义逻辑,还提供了一种在调用add和之后检查存储在其上的内容的方法。除去。
如果我这样做:
IRepo repoMock = mock(IRepo.class);
然后我有一个愚蠢的对象,对每个方法都没有任何作用。没关系,现在我只需要定义添加和删除行为。
我可以创建一个Set<String>
并只存储那两个方法来处理该集合。然后我将实例化一个具有IRepo的Holder,注入部分存根模拟,并在执行持有者之后,检查该集以验证它包含它应该是什么。
我设法使用不推荐使用的方法remove
部分地删除stubVoid
之类的void方法:
Set<String> mySet = new HashSet<>();
stubVoid(repoMock).toAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
String[] stringsToDelete = (String[]) args[0];
mySet.removeAll(Arrays.asList(stringsToDelete));
return null;
}
}).on().remove(Matchers.<String>anyVararg());
但是已被弃用,并且它比为IRepo创建部分实现要好得多。还有更好的方法吗?
注意:Java 7只能解答,这应该在Android中运行。
答案 0 :(得分:12)
您可以使用
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
//DO SOMETHING
return null;
}
}).when(...).remove(Matchers.<String>anyVararg());
来自Javadoc:
如果要使用泛型存根void方法,请使用doAnswer() 回答。
Stubbing void需要与Mockito.When(Object)不同的方法 因为编译器不喜欢括号内的void方法......
示例:
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
Mock mock = invocation.getMock();
return null;
}}).when(mock).someMethod();
请参阅javadoc for Mockito中的示例
答案 1 :(得分:2)
假设你有
public class IFace {
public void yourMethod() {
}
}
然后嘲笑你需要
IFace mock = Mockito.mock(IFace.class);
Mockito.doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
//PUT YOUR CODE HERE
return null;
}
}).when(mock).yourMethod();
答案 2 :(得分:0)
如果您在return null
的实现中真的不喜欢Answer
,那么您可以创建自己的Answer实现,委托给void方法:
public abstract class DoesSomethingAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
doSomething(invocation);
return null;
}
protected abstract void doSomething(InvocationOnMock invocation);
}
然后你的测试少了一行:
Set<String> mySet = new HashSet<>();
Mockito.doAnswer(new DoesSomethingAnswer() {
@Override
protected void doSomething(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String[] stringsToDelete = (String[]) args[0];
mySet.removeAll(Arrays.asList(stringsToDelete));
}
}).when(repoMock).remove(Matchers.<String> anyVararg());
或者,如果您只需要调用的参数:
public abstract class DoesSomethingAnswer implements Answer<Void> {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
doSomething(invocation.getArguments());
return null;
}
protected abstract void doSomething(Object[] args);
}