Over a million developers have joined DZone.

Incompatibility between TDD, Mocking and Static Methods

· Java Zone

Learn more about Kotlin, a new programming language designed to solve problems that software developers face every day brought to you in partnership with JetBrains.

Today I installed Jenkins CI and started building PODAM. I write all my code using TDD. The public API in PODAM offers a single method for now:

POJO myPojo = PodamFactory.createDummyPojo(POJO.class);

I decided to provide developers with a very simple-to-use API . For a complete list of PODAM requirements, please refer to my previous post.

So far I just wrote a single unit test which led to this piece of functionality:

     /**
* Generic method which returns an instance of the given class filled with
* dummy values
*
* @param <T>
* The type for which a filled instance is required
* @param dto
* The name of the class for which an instance filled with values
* is required
* @return An instance of <T> filled with dummy values
*
* @throws PodamMockeryException
* if a problem occurred while creating a POJO instance or while
* setting its state
*/
public static <T> T mockDto(Class<T> dto) {

try {
return dto.newInstance();
} catch (InstantiationException e) {
throw new PodamMockeryException(
"An exception occurred while instantiating " + dto, e);
} catch (IllegalAccessException e) {
throw new PodamMockeryException(
"An exception occurred while instantiating " + dto, e);
}

}

 

The unit test is as follows:

@Test
public void testSimpleDtoGraphGetsSet() {

SimpleGraphTestPojo dto = PodamMocker.mockDto(SimpleGraphTestPojo.class);
Assert.assertNotNull("The object cannot be null!", dto);

}

 

This is obviously only the beginning but following TDD practices it was my first passing test.

I then decided to use the Jenkins CI Emma plugin to check code coverage and was really surprised when I got 50% at class level. Upon investigation the Emma plugin showed me that I didn't test the branches for InstantiationException and IllegalAccessException. Static methods cannot be mocked since these are resolved at compile time.It turns out that either one has to write an interfaced service (maybe exposed as a Singleton) or that one has to give up testing every single branch of a static method when such branch throws Exceptions difficult to reproduce.

Nowhere is written that service classes (e.g. non instantiable classes with static methods) are a bad thing; on the contrary, Effective Java 2nd Edition, in Item 4, suggests that such utility classes have their uses. As a developer, if I had to decide between:

POJO myPojo = PodamFactory.createDummyPojo(POJO.class);

and

PodamFactory factory = PodamFactoryImpl.getInstance();//Singleton

POJO myPojo = factory.createDummyPojo(POJO.class);

I'd prefer the former; the latter looks a lot of boilerplate code. 

So it turns out that if one wants to use utility classes which expose static methods, and such methods throw internallly exceptions difficult to reproduce, one has to give up full coverage. Between having 100% coverage and ugly syntax on one side and 50% coverage with easy-to-use syntax on othe other, I chose the easy syntax.

 

From http://tedone.typepad.com/blog/2011/04/incompatibility-between-tdd-mocking-and-static-methods.html

The Java Zone is brought to you in partnership with JetBrains.  Discover how powerful static code analysis and ergonomic design make development not only productive but also an enjoyable experience.

Topics:

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}