在Mockito进行连续通话测试

时间:2013-11-25 13:00:37

标签: java junit mockito

我有简单的服务

package net.betlista;

import java.util.List;

public class MyServiceImpl implements MyService {

    MyDao dao;

    public void saveAll(final List<Integer> list) {
        for (final int i : list) {
            dao.save(i);
        }
    }

    void setDao(final MyDao dao) {
        this.dao = dao;
    }

}

和DAO

package net.betlista;

public class MyDaoImpl implements MyDao {

    public void save(final Integer i) {
        // do nothing, ok for tests
    }

}

我希望与Mockito一起测试,当我调用service.saveAll()时,会为列表中的所有实例调用save()调用:

package net.betlista;

import java.util.LinkedList;
import java.util.List;

import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;

public class MyServiceTest {

    @Test
    public void test() {
        final MyDao daoMock = Mockito.mock(MyDao.class);
        final MyServiceImpl service = new MyServiceImpl();
        service.setDao(daoMock);

        final List<Integer> list = new LinkedList<Integer>();
        list.add(1);
        list.add(2);

        service.saveAll(list);

        // not working, it's ok, should fail
        //        Mockito.verify(daoMock).save(Matchers.eq(1));
        //        Mockito.verify(daoMock).save(Matchers.eq(1));

        final InOrder inOrder = Mockito.inOrder(daoMock);
        inOrder.verify(daoMock).save(1);
        inOrder.verify(daoMock).save(1); // change 1 to 2 to fix test

        Mockito.verify(daoMock);
    }

}

注释部分不起作用=它通过,但应该失败。

使用InOrder,但实际上我对顺序不感兴趣(例如,如果使用set而不是list,则命令未知)。

任何想法,或者我只是想做一些毫无意义的事情?

3 个答案:

答案 0 :(得分:4)

执行此操作的最佳方法是使用ArgumentCaptor

service.saveAll(list);

ArgumentCaptor<Integer> values = ArgumentCaptor.forClass(Integer.class);
verify(daoMock, times(list.size())).save(values.capture());
assertEquals(list, values.getAllValues());

ArgumentCaptor使您可以访问传递给此方法的所有值。所以没有必要担心这种方法是否被称为“额外”时间;并且在原始列表中出现两次相同值的情况下没有问题。

答案 1 :(得分:2)

  

我想用Mockito测试当我调用service.saveAll()时,为列表中的所有实例调用save()调用

好的,那怎么样:

service.saveAll(list);

for (int i:list)
{
    Mockito.verify(daoMock).save(Matchers.eq(i));
}

我不完全确定为什么你认为注释掉的行会失败,但我猜它是因为你想确保它只调用一次?如果是这样,那么它传递它的原因是因为它只被调用过一次,但是,你的测试代码正在验证两次它只被调用一次并没有多大用处。上面的代码将验证是否为列表中的每个项调用了save方法一次(并且只调用一次)。

答案 2 :(得分:1)

 Mockito.verify(daoMock, Mockito.times(2)).save(Matchers.eq(1));

由于您要验证相同的值,请使用times()

然而,更好的方法是测试你想要的调用数量正是使用verifyNoMoreInteractions

所以测试会是这样的:

 verify(daoMock).save(1);
 verify(daoMock).save(2);
 verifyNoMoreInteractions(daoMock);