Everything that has an identity should be an Entity, and everything that does not have an identity is a simple value, hence a value object.
To quote Martin Fowler (which in turn qoutes Eric Evans)
- Entity: Objects that have a distinct identity that runs through time and different representations. You also hear these called "reference objects".
- Value Object: Objects that matter only has the combination of their attributes.
Reason to make your address a Value Object:
If your address is mutable, you will likely screw up your mailing history in the end. For example, if you're shipping items to an customer, you can't be sure to which address you actually shipped something in the past if the address your MailingHistory table is referring to has been changed.
The MailingHistory entry We shipped A764 to address 657 could mean We shipped article A764 to Boston yesterday and We shipped article A764 to New York tomorrow.
If the mailing address has to been changed, there's no need to delete the old one. Keep it, and mark it as inactive, and the new one as active.
Of course you could treat your address as a Entity, but only when updating it would not change the actual place the address is referring to, hence only allowing the correction of typos.
If you're sure you could ensure that, than using an Entity would be possible.
But the best solution IMHO is to not referrence an address Entity in your mailing history, but rather save the specific address directly in your mailing history table (basically copying the data of the address).
This way, you always know where you shipped your stuff (or whatever you are mailing), and since you would use a mutable Entity, your address table won't be cluttered up.
I've worked with/on several ERP systems, and nearly all of them used this approach.
You will have some redundancy in your database, but it's the most pragmatic way IMHO.
Going by the book (Evans, 2004), "An object defined primarily by its identity is called an ENTITY". This definition is independent of whether the object is mutable or immutable. I think it's much less likely for an immutable object to be an entity in a given domain, so it's a useful heuristic for deciding whether an object is a "value object" or an "entity", but that's not part of the definition.
For example, let's say you have an entity representing an employee, who may or may not have a direct supervisor. If you decide to represent the idea of not having a direct supervisor as being a reference to a "null" supervisor object, then the "null" supervisor object is reasonably considered an entity. And you could probably make this "null" object immutable.
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).