views:

70

answers:

4

Im trying to unit test a class in some Java code that I've inherited.

Problem is that it derives from a class that is part of the company's application framwwork. Upon construction, the base class does all sorts of 'clever' stuff, initialising connections to all kinds of services that are needed at runtime.

But for unit testing purposes I dont need any of that. I just need to create an instance of the derived class and then I can excercise it. If any test specifically need part of the hierarchy I can mock them out.

So how do I break this dependency?

+3  A: 

So you have a base class and an extended class. See if you can refactor the extended class to no longer extend the base class, but use it instead. So where you first called parent::fooBar(), you now call this.baseInstance.fooBar(). This way, you can inject another baseInstance for test purposes.

If you really need to extend the base class to override something, extract the functionality to a third class and make the extended class a proxy. The extended class does nothing else than call methods on the third class. E.g.

protected fooBar() {
    return this.realImplementation.fooBar();
}

This way, you can test the real implementation, without instantiating the base class.

Sjoerd
+5  A: 

Inheritance can be so brittle.

Is inheritance a requirement? All that "clever" stuff that the base class is doing (e.g., establishing connections) are things that a dependency injection engine would normally be providing.

Your class sounds like it would be better off from both a testing and a runtime standpoint if you find a way to not inherit and get its dependencies satisfied by a DI engine. Possible?

duffymo
+1  A: 

We had a similar issue.Lots of framework level classes and dependencies. We solved it using DI

ram
I think Guice is the best DI framework, Spring is too Java 1.4.
01
Java 1.4? With configuration by annotation? Not so. It would be fair to point out that it was conceived as a response to deficiencies in J2EE and EJB 2.0, but "too Java 1.4" isn't correct. Guice may be a fine DI framework, but Spring is far more than that. It's persistence, messaging, remoting, and lots more built on top of DI and AOP.
duffymo
A: 

I agree with the others who suggest that dependency injection is the way to go in the long term. As a short term hack, you could try to introduce a "global" flag that disables the clever initialization code for testing.

Stephen C