[ACCEPTED]-Different Singleton instances with JUnit tests-singleton

Accepted answer
Score: 20

I assume you have a private static field 6 within your singleton class to store the 5 initialized instance.

If you do not want 4 to modify your code, you can define a teardown 3 method which run after every test, and in 2 this method you set this static field to 1 null via reflection as seen here.

Score: 15

Don't use a singleton.

Specifically, the 13 only difference between a singleton and 12 a global variable is that the singleton 11 tries to enforce a single instance (by making 10 the constructor private, for example).

Instead, make 9 the constructor public and write tests using 8 new instances. In your actual program, use 7 getInstance() to get the canonical global instance (or 6 use an IOC container).

And remember that 5 singletons are pathological liars.

If you're still too comfortable with the 4 idea of a Singleton, instead of making the 3 constructor public you can add a public 2 (and static) factory method to create instances 1 in a way that can't be used by accident, e.g.:

public static MyClass TEST_CreateInstance() {
  return new MyClass();
}
Score: 3

You can add a method to destroy the singleton, for 6 example destroyMe(); where you deinitialize 5 everything and set the instance of the singleton 4 to null.

  public void destroyMe(){
   this.instance = null;
   //-- other stuff to turn it off.
}

I will leave synchronization problems 3 though ;)

But why do you need to re-initialize 2 your singleton for each test? It should 1 not differ based on the concept of the singleton.

Score: 3

Spring provides the DirtiesContext annotation for this 5 particular use case where you need new instances 4 of the singleton beans for each testcase. It 3 basically creates a new application context 2 for each testcase/testclass which has this 1 annotation applied.

Score: 2

I highly recommend moving away from Singletons as a design 13 pattern, and using Singleton as a scope 12 (Dependency Injection). This would simply 11 make your problem go away.

But assuming 10 you are stuck in the world of Singletons, then 9 you have a few options depending on if you 8 are testing the Singleton or the dependency.

If 7 you are testing the dependant item then 6 you can mock the Singleton using PowerMock and JMockIt. See 5 my previous post about mocking Runtime.getRuntime for 4 instructions on how to go about this.

If 3 you are testing the Singleton then you need 2 to relax the rules on construction, or give 1 the Singleton a "Reset" method.

Score: 1

generally beware of singletons, most often 6 they are evil, bad design and tend to represent 5 big yucky global variables (which is bad 4 for maintenance).

still to get tests in place 3 first you can do:


static setInstance(...){ //package visibility or in difficult cases you have to use public
  instance = ...;
}

as said this is more a 2 workaround. so get first tests place, but 1 then refactor away from singleton pattern.

Score: 0

Singleton instance needs to be passed to 4 SUT by test itself - that way you create 3 singleton (and destroy) for each test. Adopting 2 IoC and mocking framework, like Mockito, would 1 render this approach almost trivial.

More Related questions