Domain-Driven Design – Should Entities and Value Objects Be Mocked in DDD?

domain-driven-designobject-orientedtddunit testing

After reading a few articles about Newable vs Injectable objects and how these concepts relate to DDD's services, entities and value objects, I was left with some doubts about using newables in my code especially in my unit tests.

Main candidates for newables were Entities and Value objects meaning that instead of injecting these dependencies into other objects one should just new an instance of these objects and use them directly in the code.

However, good DDD practices advocate assigning responsibilities to entities and value objects if they were deemed appropriate. So the entities and value objects will end having some serious business logic in them.

Now if a service operates on an entity or a value object should I mock the entity or value object and pass the mock to the service (mocking will require an interface for the value objects or entities which seems to be advocated against) ?

Or should I just new an entity/value object and pass a concrete implementation to the service and thus violating the unit testing principle of testing only one unit?

Best Answer

I'm reading that you're of the opinion that unit tests, much like SOLID objects, must have "one reason to break". It's a noble goal, but I think you'll find that in many cases it is simply not feasible. One of those cases is here, where you have a "rich" domain object (DDD differentiates between Entities and Value Objects, which both comprise the "domain model") that is a dependency of the system under test.

In these situations, I have the philosophy that, given the domain object has its own comprehensive unit test coverage, trusting that the object will work as designed in a unit test for a different SUT does not necessarily violate the unit test. If this test were to break because of a breaking change to the domain, then I would expect the domain object's unit test to break as well, leading me toward something to investigate. If the domain object's unit test had been updated properly as a red test, then made green with the change, and this other test then failed, that's not necessarily a bad thing either; it means that the expectations of this other test conflict with the new expectations for the domain, and I need to make sure both of them agree with each other and the overarching acceptance criteria of the system.

As such, I would only mock a domain object if said domain object produced "side effects" that were undesirable from a unit-testing perspective (i.e. touching external resources like data stores), or if the logic of the domain object were sufficiently complex that placing it in the proper state for the test becomes a roadblock to defining and passing the test.

That then becomes the driving question; which is easier? To use the domain object for its intended purpose within the test, or to mock it? Do whichever is easier, until it's no longer the easier option, such as when a functional change breaks the test of the service in a complex way; if this happens, then rewrite the test to produce a mock that exposes the functional requirements depended on by the service, without the complexity that breaks it.

Understand that either way, there should be an integration test that uses the real domain object plugged into the real service that tests the interaction between these two at a higher level of abstraction (such as testing, for instance, not only the functionality behind a service endpoint, but a proxy across which the domain object is serialized and sent).