Unit Testing a Singleton Using PowerMock

I came across an interesting problem this week at work. I had to make some changes to a Singleton class in Java, and had some issues when trying to unit test the changes. When JUnit runs each test method with the @Test annotation, a new object of the test class is instantiated, this ensures that there are no side effects between test cases. However, the Singleton class that is under test returns a reference to it's object upon each invocation of it static factory method. This can be a problem for your test cases because they are referencing the same object under test, opposed to a new one, which can cause side effects from previous tests.

Luckily you can get around this issue using PowerMock. The code snippets below show how to do this yourself...

Code Example

SingletonTest.java
1|    package test;
2|      
3|    import static org.junit.Assert.fail;
4|    import main.Singleton;
5|      
6|    import org.junit.Before;
7|    import org.junit.Test;
8|    import org.junit.runner.RunWith;
9|    import org.powermock.modules.junit4.PowerMockRunner;
10|   import org.powermock.reflect.Whitebox;
11|     
12|   @RunWith(PowerMockRunner.class)
13|   public class SingletonTest {
14|       private Singleton objUnderTest;
15|     
16|       @Before
17|       public void setup() {
18|           try {
19|               objUnderTest = 
20|                   Whitebox.invokeConstructor(Singleton.class);
21|           } catch (Exception e) {
22|               fail(e.getMessage());
23|           }
24|       }
25|     
26|       @Test
27|       public void singletonInstance1() {
28|           System.out.println("Singleton class instance 1: " 
29|               + objUnderTest);
31|       }
32|     
33|       @Test
34|       public void singletonInstance2() {
35|           System.out.println("Singleton class instance 2: " 
36|               + objUnderTest);
37|       }
38|    }

Lines # 19 and 20 invoke the private constructor of the test class below to ensure that a new object is created before each test case.

Singleton.java
1|    package main;
2|    
3|    public class Singleton {
4|        private static Singleton singleton;
5|    
6|        private Singleton(){}
7|    
8|        public static Singleton getInstance() {
9|            if(singleton == null)
10                singleton = new Singleton();
11|           return singleton;
12|       }
13|   }
Console Output
Singleton class instance 2: main.Singleton@4445629
Singleton class instance 1: main.Singleton@3d51f06e

From looking at the test console output, we can see that the objects in each test case are different. Thus, a way to remove side effects between test cases when unit testing a Singleton!

Comments

Popular posts from this blog

Mocking Super Class Method Invocations with PowerMock

Verifying Static Method Calls