2

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

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 的 delete(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 文档强烈反对使用这种类型的部分模拟,基本上声明它应该只用于临时遗留代码和第 3 方 API。有什么更好的解决方案?

4

1 回答 1

1

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

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

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

于 2012-08-24T21:18:04.910 回答