nocandies
nocandies

Reputation: 33

Can not make the mocked singleton's method behave differently in different test cases

The unit test of a class is involved with a static method in a another class, say HelperClass. HelperClass has a singleton member. I used Junit for the unit tests and Powermockito to mock the singleton member. But I found that the behavior of the method of the singleton member can only be specified once.

//the class to be tested
class Activity {
    public void enact() {
        //some logic
        String str = HelperClass.doSomething();
        //some other logic
    }
}

class HelperClass {
    private static final singleton = Singleton.getInstance();
    public static String doSomething() {
       //some logic
       AnObject obj;
       try {
           obj = singleton.doSomething();
       } catch (Exception1 e) {
           //Some other logic
           throw new Exception2("Some message" + e.getMessage(), e);
       }

       String val = obj.doSomething();
       return val;
    }
}

class Singleton {
    private Singleton instance = null;
    private void Singleton() { /*some logic*/ }
    public static Singleton getInstance() {
        if (instance == null) {
            Singleton();
        }
        return instance;
    }
    public String doSomething() throws Exception1 {
        //some logic
    }
}

My uint test goes like this

@RunWith(PowerMockRunner.class)
@PrepareForTest(Singleton.class)
class ActivityTest {
     //some logic
     private Activity activity;

     @Before
     public void setup() {
         //some logic
         PowerMockito.mockStatic(Singleton.class);
         activity = new Activity();
     }

     @Test(expected = Exception2.class)
     void test1() {
        Singleton mockSingleton = mock(Singleton.class);
        when(mockSingleton.doSomething()).thenThrow(new Exception1("Test Exception1"));
        PowerMockito.when(Singleton.getInstance()).thenReturn(mockSingleton);

        activity.enact();
     }

     @Test
     void test2() {
        Singleton mockSingleton = mock(Singleton.class);
        when(mockSingleton.doSomething()).thenReturn("");
        PowerMockito.when(Singleton.getInstance()).thenReturn(mockSingleton);

        activity.enact();
     }
}

But it does not work. Although I specify different behaviors of the doSomething() of the mockSingleton, the mockSingleton still throws the Exception2 in test2 as it does in test1. It seems that the behavior can only be specified once. Can somebody tell me how I can let the doSomething() here have different behaviors?

Upvotes: 2

Views: 228

Answers (1)

johnnyaug
johnnyaug

Reputation: 1163

You are calling Signleton.getInstance only once - when HelperClass is initialized. This way you always use the mock from your first test. To solve this, you can call getInstance every time you need an instance of Singleton.

Thus, the code for HelperClass would be:

class HelperClass {
    public static String doSomething() {
       //some logic
       AnObject obj;
       try {
           obj = Singleton.getInstance().doSomething();
       } catch (Exception1 e) {
           //Some other logic
           throw new Exception2("Some message" + e.getMessage(), e);
       }

       String val = obj.doSomething();
       return val;
    }
}

This way, you will get the right mock on every run.

Upvotes: 1

Related Questions