单元测试 – 如何保持单元测试简单和隔离,并仍然保证DDD不变量?

DDD建议域对象随时都应处于有效状态.聚合根负责保证不变量和工厂组装具有所有必需部分的对象,以便它们在有效状态下初始化.

然而,这似乎使创建简单,孤立的单元测试的任务复杂化.

假设我们有一个包含Books的BookRepository.一本书有:

>作者
>一个类别
>您可以在其中找到该书的书店列表

这些是必需的属性:一本书必须有一个作者,一个类别和至少一个书店,你可以从中购买这本书.
可能有一个BookFactory,因为它是一个非常复杂的对象,而Factory将至少用所有提到的属性初始化Book.也许我们还会将Book构造函数设置为私有(以及Factory嵌套),这样除了Factory之外没有人可以实例化一个空的Book.

现在我们想要单元测试BookRepository的一个方法,该方法返回所有的Books.为了测试该方法是否返回书籍,我们必须设置一个测试上下文(AAA术语中的Arrange步骤),其中一些Books已经存储在Repository中.

在C#中:

@H_404_16@[Test] public void GetAllBooks_Returns_All_Books() { //Lengthy and messy Arrange section BookRepository bookRepository = new BookRepository(); Author evans = new Author("Evans","Eric"); BookCategory category = new BookCategory("Software Development"); Address address = new Address("55 Plumtree Road"); BookStore bookStore = BookStoreFactory.Create("The Plum Bookshop",address); IList<BookStore> bookstores = new List<BookStore>() { bookStore }; Book domainDrivendesign = BookFactory.Create("Domain Driven Design",evans,category,bookstores); Book otherBook = BookFactory.Create("other book",bookstores); bookRepository.Add(domainDrivendesign); bookRepository.Add(otherBook); IList<Book> returnedBooks = bookRepository.GetAllBooks(); Assert.AreEqual(2,returnedBooks.Count); Assert.Contains(domainDrivendesign,returnedBooks); Assert.Contains(otherBook,returnedBooks); }

鉴于我们可以创建Book对象的唯一工具是Factory,单元测试现在使用并依赖于Factory,并且仅依赖于Category,Author和Store,因为我们需要这些对象来构建Book然后将它放入测试环境.

您是否会认为这是一种依赖关系,就像在服务单元测试中我们将依赖于服务所调用的存储库一样?

您如何解决重新创建整个对象集群以便能够测试简单事物的问题?你如何打破这种依赖性并摆脱我们在测试中不需要的所有这些Book属性?通过使用模拟或存根?

如果你模拟了Repository包含的东西,你会使用什么样的模拟/存根,而不是当你模拟测试中的对象与之对话或消费时?

两件事情:

>在测试中使用模拟对象.您目前正在使用具体对象.
>关于复杂的设置,在某些时候你需要一些有效的书籍.将此逻辑提取设置方法,以在每次测试之前运行.让该设置方法创建有效的书籍集合等等.

“How would you solve the problem of
having to re-create a whole cluster of
objects in order to be able to test a
simple thing ? How would you break
that dependency and get rid of all
these Book attributes we don’t need in
our test ? By using mocks or stubs ?”

模拟对象可以让你这样做.如果测试只需要一本有效作者的书,那么您的模拟对象将指定该作者,其他属性将被认.由于您的测试只关心有效的作者,因此无需设置其他属性.

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...