Code Monkeyism

Programming is hard by Stephan Schmidt

JUnit recipes: Work around static attributes in classes

Beware of the class loader. I recently had a major testing problem with some code because I didn’t take the (sometimes ugly) Java class loading mechanism into account. There was a small class where I wanted to unit test the calculateAge method.

class AgeCalculator {
    public int calculateAge(Person person) {
      ....
    }
}

So I dropped EasyMock into my project and mocked the person class. I was using jMock in the past and could live with methods as strings. With the new JMock 2 syntax this has changed. I still struggle with {{ in JMock expectations and so does my IDE. When IDEA learns to format JMock expectations, I’m back. For now I’m using EasyMock though, sometimes with JMock assertions from the excellent Hamcrest assertion library. Back to the problem at hand . The mock was passed into the AgeCalculator to calculate the age of the person. The problem was the Person class.

class Person {
  private static Configration conf =
    new DatabaseConfiguration("Person");
    ...
}

Even though I didn’t use the Person class, just a mock, the static attributes where initialized and the DatabaseConfiguration tried to load data from the backend. This happens whenever your classloader sees the Person type, even in an interface.

interface Calculator {
    public int calculateAge(Person person);
}

Using Calculator in mocks will initialize the static attributes in Person. Which contradicted the isolation principle of unit tests and also led to long startups of the database backend. This stopped my efforts to test the AgeCalculator. Time passed.

Then I stumbled upon JMockit. Others have too. The friendly and supportive developers of JMockit have helped (thanks Rogerio) and with a simple line I was saved:

Mockit.redefineMethods(
  DatabaseConfiguration.class,
  MockDatabaseConfiguration.class
);

Constructs like the above with static attributes should never be created in the first place (hello all those people who propagate static inialized attributes for singletons to avoid synchronized). But if you have such code in your legay base, JMockit to the rescue.

Thanks for listening.

About the author: Stephan Schmidt is currently a team manager at ImmobilienScout24 in Berlin. Stephan has been working as a head of development and CTO. He has used a lot of different technologies in the last 20 years including Java, Rails and Python. Stephans main field of interest is maintainablity and productivity in software development. Want to know more? All views are only his own.

If you did like this article but you don't want to subscribe to new articles with your reader, you can follow me on Twitter or subscribe to new posts with your email:

Comments

[...] JUnit recipes: Work around static attributes in classes- Some hip advice here. [...]

Thomas Hawk

I am curious as to why you need an AgeCalculator class with a calculateAge method. I, of course, am not familiar with your code, but it seems to me calculateAge should be a method in the Person class.

stephan

@Thomas: The names have been changed to protect the innocent :-)

But as a side node, I’ve been moving further and further away from OO to a data holder object and service programming style. Any business logik inside of objects looks now suspicious to me. I think services like AgeCalculator are much more versatile and exchangable.

Qrilka

I think the problem is in using concrete classes not interfaces. So If Person would be just an interface you won’t have such situation. Concrete classes enlarge code coherence and create problems like the one you’ve mentioned.

stephan

@Qrilka: Yes you’re right. I most often use interfaces instead of classes, but this was legacy code which couldn’t easily be changed.

But although most people would use interfaces for services (storage, view), I seldom see people using interfaces for business objects like Person.

stephan

Thinking about that again, as Qrilka said, the problem (in this case) arises from interfaces depending on classes. So interfaces should only depend on other interfaces, not on concrete classes.

Thnks for your comment.
I have to work around with Legacy Code a lot. Client usually do not allow us to change the design. So sometime I have to use stubbed classes or jMockit.

Leave a Reply