views:

706

answers:

7

I am writing unit tests for a class, which has a static final variable. However, since the state of the static final var is modified in each test, I need some way to reinitialize it.

How would this be possible? Would i need to use some sort of a custom classloader?

The variable is initialized as -

 static final CountdownLatch latch = new CountdownLatch(1);

+2  A: 

One (not very efficient) approach assuming you are using junit and ant.

You could create a separate class for each test method, and then use a forkmode of perTest.

As the ant junit task documentation states:

Controls how many Java Virtual Machines get created if you want to fork some tests. Possible values are "perTest" (the default), "perBatch" and "once". "once" creates only a single Java VM for all tests while "perTest" creates a new VM for each TestCase class. "perBatch" creates a VM for each nested <batchtest> and one collecting all nested <test>s. Note that only tests with the same settings of filtertrace, haltonerror, haltonfailure, errorproperty and failureproperty can share a VM, so even if you set forkmode to "once", Ant may have to create more than a single Java VM. This attribute is ignored for tests that don't get forked into a new Java VM. since Ant 1.6.2

toolkit
+1  A: 

How do you initialize the static final variable in the first place?

Maybe you can mock the method that initializes the variable?

Example: static final int number = getNumber();

By mocking the getNumber()-method to return the value you want you can control the 'number' variable.

Someone
i dont use a method to initialize the variable.
pdeva
A: 

The only way I can think that a "final" variable is getting modified, through unit tests or otherwise, would be through byte code manipulation.

George Jempty
The problem might be when using something like:final MyMutableObject mmo = new MyMutableObject();mm.setSomething("ssssdsds");
Dev er dev
yes, that is what it is.
pdeva
A: 

Editing the comment to make plain the point that the variable in question is static, and hence exists once in the JVM.

Variables marked final are only ever modified once, which seems to occur once in your different tests. If you're using JUnit, why not create a new instance of the class in every call of setup(), which in itself gets called before every test. This would be the quickest, and most representative of your situation.

Spencer K
its a 'static final' , not just a 'final'.
pdeva
hrm... good point. It's early in the morning for me. =D
Spencer K
+4  A: 

Of course you can hack around it with reflection or class loading, but "if I were you, I wouldn't be starting form here." Mutable statics are really evil (even those called singletons). So, design you code better by "parameterisation from above" - pass object into those that need them, rather than doing something hardwired or using a directory service.

Tom Hawtin - tackline
A: 

Static finals are constants, that means they aren't mutable. Why do you test them with different values?

A good static final variable, is one holding some state about your environment. For instance a variable with your OS. You will not even change it in testing. This case you need to test on different machines (or at least virtual machines).

But you want to test this variable with different values. So it seems one of the modifiers is wrong here, static or final, one of them don't matches the semantics you need here, otherwise you wouldn't want to test it with different values.

Can you provide some more detail about the problem?

Mnementh
+3  A: 

You can change static finals since JDK 1.5 through reflection. (see this link for a code example) ...but I would advice you not to. In fact it has shown over the past that static variables should be avoided if possible. Commons Logging is a good example. (check out the explanation here).

So if possible get rid of the final and even the static. If that is no option you can write a helper function that does it via reflection. But that surely is the worst option.

cheers, Torsten

tcurdt