How to keep your unit tests simple and isolated and still guarantee DDD invariants ?
- by ian31
DDD recommends that the domain objects should be in a valid state at any time. Aggregate roots are responsible for guaranteeing the invariants and Factories for assembling objects with all the required parts so that they are initialized in a valid state.
However this seems to complicate the task of creating simple, isolated unit tests a lot.
Let's assume we have a BookRepository that contains Books. A Book has :
an Author
a Category
a list of Bookstores you can find the book in
These are required attributes : a book has to have an author, a category and at least a book store you can buy the book from.
There's likely to be a BookFactory since it is quite a complex object, and the Factory will initialize the Book with at least all the mentioned attributes.
Now we want to unit test a method of the BookRepository that returns all the Books. To test if the method returns the books, we have to set up a test context (the Arrange step in AAA terms) where some Books are already in the Repository. If the only tool at our disposal to create Book objects is the Factory, the unit test now also uses and is dependent on the Factory and inderectly on Category, Author and Store since we need those objects to build up a Book and then place it in the test context.
Would you consider this is a dependency in the same way that in a Service unit test we would be dependent on, say, a Repository that the Service would call ?
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 attributes we don't need in our test ? By using mocks or stubs ?
If you mock up things a Repository contains, what kind of mock/stubs would you use as opposed to when you mock up something the object under test talks to or consumes ?