The Law of Demeter, also know as the Principle of Least Knowledge, is important to controlling the type population of a test subject. Here is a fun explain from c2.com:
- You can play with yourself.
- You can play with your own toys (but you can’t take them apart),
- You can play with toys that were given to you.
- And you can play with toys you’ve made yourself.
Explanation in plain English:
- Your method can call other methods in its class directly
- Your method can call methods on its own fields directly (but not on the fields’ fields)
- When your method takes parameters, your method can call methods on those parameters directly.
- When your method creates local objects, that method can call method on the local objects.
The paper Mock Roles, not Objects contains a good example:
should really be:
To be clear the example code above would be contained in the test subject. The bad example couples the test subject to DogAnimal, DogBody, and DogTail. Where as the good example couples only to DogAnimal. This smell has always reminded me of a violation of the Single Responsibility Principle. These symptoms indicate a violation of the Law of Demeter:
- To Many Mock Objects
- To Much Mock Setup
- Mock Object Chaining
“Compliance to the Law of Demeter reduces the number of interfaces, the number of stubs and drivers that may be needed, and the number of integration test interfaces.” – Reviewing Software Artifacts for Testability by Stefan Jungmayr
Interestingly Endo-Testing Unit Testing with Mock Objects by Tim Mackinnon, Steve Freeman and, Philip Craig presents the view that “…code developed with Mock Objects tends to conform to the Law of Demeter, as an emergent property. The unit tests push us towards writing domain code that refers only to local objects and parameters, without an explicit policy to do so.” I am not so sure that use of mocks naturally leads to conformance to the Law of Demeter. Martin Fowler noticed that developers that perform interaction based testing tend to follow the Law of Demeter (Mocks Aren’t Stubs):
“Interaction-based testers do talk more about avoiding ‘train wrecks’ – method chains of style of
getThis().getThat().getTheOther(). Avoiding method chains is also known as following the Law of Demeter. While method chains are a smell, the opposite problem of middle men objects bloated with forwarding methods is also a smell. (I’ve always felt I’d be more comfortable with the Law of Demeter if it were called the Suggestion of Demeter.) One of the hardest things for people to understand in OO design is the “Tell Don’t Ask” principle, which encourages you to tell an object to do something rather than rip data out of an object to do it in client code. Interaction testers say that using interaction testing helps promote this and avoid the getter confetti that pervades too much of code these days.”
Mock Object Patterns by Matthew A. Brown and Eli Tapolcsanyi includes the pattern Pass in Mock Collaborator. In the implementation section of the pattern they direct you to use “… the Law of Demeter, design your method calls to permit easy testing” of the test subject.
I think the basic underlining issue with violations of the Law of Demeter is misplaced responsibility. I suspect that this is why it is also called the Principle of Least Knowledge and why it reminds me of the Single Responsibility Principle. Part of correctly assigning responsibility is dependency management an testability is very sensitive to dependency issues.
Some people get concerned about interaction based testing coupling the unit test to the implementation of the test subject. It can if a test double is used in place of an object that the test subject uses as a helper (i.e. the interaction of the test subject with the helper is not a responsibility of the test subject). In general you should only ever use test doubles where it is the responsibility of the test subject to perform the interaction. Please notice I said responsibility of the test subject and not the system. A test subject plays a role in a system and that role has responsibilities which include interaction, maybe even entirely comprised of, with other objects in the system. When you refactor a class, or test subject, in a system it is still responsible for interacting with the same objects it did before the refactoring. When you change its interactions, or move the responsibility to an other class, you are refactoring the system. When refactoring the system unit tests should break. When refactoring a class unit tests should not break.17,190 Total Views