Mockito:如何在调用时使用void方法来运行一些代码

时间:2015-08-21 11:33:25

标签: java unit-testing mockito void stubbing

我想存根一个存储库类来测试另一个具有存储库的类(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
}

我想创建一个存储库模拟,它可以存储实例,仅为addremove定义逻辑,还提供了一种在调用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中运行。

3 个答案:

答案 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);
}
相关问题