Law of Demeter is easy to spot when you need extra mocks

Spread the love

Law of Demeter is easy to spot when you need extra mocks

In code, the Law of Demeter (aka the one-dot rule) is a principle that basically states:

void DoSomething(IFoo foo){    foo.GetStatus(); // good}void DoSomething(IFoo foo){    foo.Profile.GetStatus(); // bad}

In this example, DoSomething() knows intimate details about what an IFoo’s insides look like. This is bad because it’s additional coupling that will bog us down later — if we ever want to change the internal composition of IFoo, we will have to also update all pervert methods like DoSomething() that depend on it.

In some situations, this rule really doesn’t matter, e.g. for trivial or built-in types (datasets come to mind). But other times we definitely want to avoid it. One trick I have discovered for identifying trouble spots is a code smell you might encounter when isolating something for unit testing:

var foo = new Mock<IFoo>();var profile = new Mock<IProfile>();profile.Setup(p => p.GetStatus()).Returns(/* the thing we are testing */);foo.SetupGet(f => f.Profile).Returns(profile);DoSomething(foo.Object); // assert etc

Does this code look familiar? In it we are setting up two mocks:

  • The Profile instance, which has a method we want to stub out and verify
  • The parent IFoo, which only exists to return the child Profile

The code smell is all the extra setup cruft required — two levels of nested mocks for just one parameter we are testing. If we do move method and provide a GetStatus() method on IFoo (that internally delegates to Profile), our test immediately becomes a lot clearer:

var foo = new Mock<IFoo>();foo.Setup(p => p.GetStatus()).Returns(/* the thing we are testing */);DoSomething(foo.Object); // assert etc