在这种情况下,部分嘲笑有什么问题?

时间:2012-08-24 20:43:44

标签: java unit-testing mocking mockito partial-mocks

假设我有两种方法,其中一种基本上是另一种方法的包装器,只需要一点点额外的处理:

public class ItemRepositoryImpl implements ItemRepository {

    ...

    @Override
    public void delete(UUID itemID) {

        Item item = findOne(itemID);
        delete(item);
    }

    @Override
    public void delete(Item item) {

        // Do a bunch of stuff that needs a lot of tests run on it, like
        //    deleting from multiple data sources etc
        ...
    }
}

为部分抄袭ItemRepositoryImpl的删除(UUID)方法编写单元测试有什么问题,并检查delete(UUID)最终是否调用delete(Item)?如果我这样做,我就不必为每个删除方法写一堆重复的测试!

在Mockito,我可以像这样的间谍实施这样的测试:

ItemRepository spyRepo = spy(repository);       // Create the spy
when(spyRepo.findOne(itemID)).thenReturn(item); // Stub the findOne method
doNothing().when(spyRepo).delete(item);         // Stub the delete(Item) method
spyRepo.delete(itemID);                         // Call the method under test

// Verify that the delete(Item) method was called
verify(spyRepo).delete(item);

但是,Mockito文档强烈反对使用这种类型的部分模拟,基本上声明它只应用于临时遗留代码和第三方API。什么是更好的解决方案?

1 个答案:

答案 0 :(得分:1)

如果您正在进行纯单元测试并且您的测试单元是一种方法,那么我会说您在这里嘲笑的内容没有任何问题。有些人认为单元测试应采用更黑盒子的方法,并且通过模拟方法调用,您的测试对测试方法的实现了解得太多。

如果您测试的单位是一个类而不是一个方法,那么您可以简单地模拟对其他类的调用。

关于单元测试总是存在争议。这是一篇有关该主题的有趣文章,与您的问题非常相关:http://martinfowler.com/articles/mocksArentStubs.html