7

I have a java class with some static fields:

private static final PDMapCacheDAO REST_CACHE_DAO = 
    new PDMapCacheDAOImpl( Constants.REST_CACHE_NAME );

private static final PDMapCacheDAO HOLIDAYS_CACHE_DAO = 
    new PDMapCacheDAOImpl( Constants.HOLIDAYS_CACHE_NAME );

private static final String[] DATE_ARRAY = { "D", "0", "1", "2", "3", "C" };

and the JUnit test mocks that initialization behaviour for REST_CACHE_DAO and HOLIDAYS_CACHE_DAO:

final PDMapCacheDAOImpl holidaysMapCacheDAOImpl = mock(PDMapCacheDAOImpl.class);
final PDMapCacheDAOImpl restMapCacheDAOImpl = mock(PDMapCacheDAOImpl.class);

whenNew(PDMapCacheDAOImpl.class).withArguments(Constants.HOLIDAYS_CACHE_NAME).thenReturn(holidaysMapCacheDAOImpl);
whenNew(PDMapCacheDAOImpl.class).withArguments(Constants.REST_CACHE_NAME).thenReturn(restMapCacheDAOImpl);

When the tests are executed individually, the tests perform as expected, but when all JUnit tests are executed together (from the Java Project with Run As --> Junit Test) the test gives an null pointer exception.

I have done some debugging and I've found out that the problem (as stated in the title) is that the static classes aren't initialized - when the static methods are invoked the REST_CACHE_DAO and HOLIDAYS_CACHE_DAO are null. The constructor of PDMapCacheDAOImpl is not invoked and the mocks are not injected, hence when we use them, it gives a NPE.

I've read about some tools to performs test, like eclemma that have this error (some static classes are not initialized). In this case the solution is to include the -f option.

This is what the Eclemma website says about this problem:"

2.8. How is class coverage defined by EMMA? First of all, a class needs to be considered executable to even be considered for coverage. An executable class is considered to have been covered if it has been loaded and initialized by the JVM. Class initialization implies that the class static constructor (if any) is executed. Note that a class can be covered even though none of its other methods has been executed. It is common to see a small number of loaded but uninitialized classes when you use emmarun without the -f option. EMMA reports class coverage so that you could spot classes that do not seem to be "touched" by your test suite: they could be either dead code or in need of more test attention.

The interesting thing is that we are not using Eclemma, we are using Cobertura, but the behaviour and the errors are the same.

Does anyone know something about this error in Cobertura and how to solve it? (Either in Cobertura or in a generic way)?

Anders R. Bystrup
  • 15,729
  • 10
  • 59
  • 55
user2031818
  • 71
  • 1
  • 2
  • As you can see using static fields for object dependencies is a bad design. Hard testing is one of the evidences. Use instance variables for dependencies and then `@InjectMocks` will do the trick. You'll probably have more issues with that. This is why DI frameworks like Spring, Guice or CDI were invented. – Piotr Gwiazda Feb 01 '13 at 10:13
  • Which version of Eclipse (and java) are you using? – Matthew Farwell Feb 01 '13 at 10:33
  • for this development we are not allowed to use spring (i really like spring, but you know, these big enterprises ...) the point is that all of the functionality of our class is static, all methods are static. But, even in the case it is a bad practice, why this error could happen?? – user2031818 Feb 01 '13 at 10:34
  • we are using Java 6. And the version of eclipse, we have a modified version of eclipse created in the corporation i work. in fact, they translated it into spanish, which i hate because it's more difficult to find all the staff. They even change the name, the only thing i can know is that it is Version: 2.0 Build id: 20110218-0911, but i think this might refer to the platformed version of the organization – user2031818 Feb 01 '13 at 10:43
  • Have you tried moving the classes so that they are above your static initializers? – jontejj Jun 04 '13 at 15:49

2 Answers2

0

This is speculative.

I guess PDMapCacheDAO is an interface/abstract class, which uses PDMapCacheDAOImpl for some constants.

And class PDMapCacheDAOImpl implements/extends PDMapCacheDAO. Right?

As I find this a technically ugly solution (reciproke dependencies), make a separate interface PDMapCacheDAOs with these constants.

That might solve the problem.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • no, the PDMapCacheDAOImpl is not used for constants. They are just an interface and its implementation. Then the PDMapCacheDAOImpl access one or other data repository depending on the constructor parameter (Constants.HOLIDAYS_CACHE_NAME or Constants.REST_CACHE_NAME). where are the reciproke dependencies?? thanks for the quick response – user2031818 Feb 01 '13 at 10:39
  • So DATE_ARRAY also is null. Sorry, the pattern looked quite familiar: `interface T { static final T A = new TImpl(); }` against `class TImpl implements T { }`, which would be nightmarish. – Joop Eggen Feb 01 '13 at 11:25
  • yes, the DATE_ARRYA also is null. Anyway, thanks for your time – user2031818 Feb 01 '13 at 11:26
0

At the end we have decided to use Singleton instead and avoid all the problems with the static initialization. I have to say to the corporation that the problem remains and can happen again in the future, but i can't wait for the SQA team to fix it.

Thanks for all your responses and your time

user2031818
  • 71
  • 1
  • 2