Tale one, package
mismanagement
Here is an anti-pattern:
java/blarfage/Foo.java:
package blarfage; public class Foo { }
java/test/blarfage/FooTest.java:
package test.blarfage; import junit.framework.TestCase; public class FooTest extends TestCase { }
What is wrong here—where is the anti-pattern? Do not put test classes in a different package than that of the class under test. It looks clean and logical, but try it for a while and the pain of it hobbles your testing. Many useful tricks vanish, chief among them package-scope methods for tweaking the class under test. Don't just take my word for it: try it on any moderate-sized project and see for yourself.
Tale two, useful IoC trick
Here is a handy trick for configuring a class under test: provide a separate, protected constructor just for testing.
java/blarfage/Foo.java:
package blarfage; public class Foo { private final Bar favorite; public Bar(final Drink beer) { this(new Bar(beer)); } protected Bar(final Bar favorite) { this.favorite = favorite; } }
test/blarfage/FooTest.java:
package blarfage; import junit.framework.TestCase; public class FooTest extends TestCase { private TestFoo foo; protected void setUp() throws Exception { foo = new TestFoo(createMockBar()); } private static final TestFoo extends Foo { private TestFoo(final Bar favorite) { super(favorite); } } }
The idea is this: Say Bar
is complex or expensive—java.sql.Connection
is a good example. The public
constructor takes the argument for constructing the private, expensive or complex object; the protected
constructor takes the actual expensive or complex object so that a test can extend the class under test and use that protected
constructor.
This trick is especially handy when you do not have control of code using the class under test (else you might refactor the public
constructor to take the expensive or complex argument directly as the protected
constructor does).
No comments:
Post a Comment