My colleagues and I were struggling with some test ugliness- having to construct complicated object graphs so that a particular Class Under Test could get the argument it needed at test time. Typically, the CUT would have some call in it like:
a.getB().getC().getSomeField()To address this, many of our tests were using the Builder Pattern to build up these graphs. This helped somewhat, by centralizing the construction of the objects, and it also led to some some re-use of the scaffolding code. But it still didn't address the underlying problem of having to build up crazy amounts of superfluous objects for the test.
Anyone who's read Refactoring, or the Pragmatic Programmer series will recognize that the Law of Demeter is in play here. A, B, and C are too tightly coupled. We all know this is "bad", but somehow this never really bothered me much in production code. In the age of modern IDEs, it's really easy to track down who is calling whom, and to re-work the code when you feel things have gotten out of hand.
The typical remedy for fixing overly tight coupling is to use encapsulation or a delegate to hide the call chain. This never really struck me as much of an improvement, as it piled yet another interface on top of the code. Having spent too much time toiling with J2EE megaliths, I was wary of adding yet another layer.
But then when we realized what this inappropriate intimacy was doing to our tests, a light bulb went off. Adding a really small interface to class A doesn't really bloat the code, and most importantly- it gives the test code a hook where it can mock out the single call that it really cares about, ignoring the rest.
class A {
private B b;
public String getSomeField() {
return b.getC().getSomeField();
}
}
Clients of A now just call A.getSomeField(). Test code that needs an A can get a very simple mock:
A mockedA = new A() {
@Override
public String getSomeField() {
return "mockedResult";
}
}Obviously, this isn't some new industry-changing technique; it's been around forever. But as a result of applying it judiciously, our test scaffolding has been drastically reduced, and tests are easier to write and understand.
No more Russian dolls.
image credit: http://en.wikipedia.org/wiki/File:Russian-Matroshka.jpg


Wee its nick from tacolovers54.blogspot.com
ReplyDeleteNice post. Great blog. Thanks for sharing.
ReplyDeleteGroupon Clone| Formspring Clone|
I think it is so named for its origin in the Demeter Project, an adaptive programming and aspect-oriented programming effort
ReplyDelete^ I think you need to fuck-off of there and stop stole phrases of other peoples
ReplyDelete