不能使模拟的单例方法在不同的测试用例中表现不同

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

class 的单元测试涉及另一个class 中的静态方法,比如说HelperClassHelperClass 有一个单例成员。我使用 Junit 进行单元测试,使用 Powermockito 模拟单例成员。但是我发现单例成员的方法的行为只能指定一次

//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
    }
}

我的 uint 测试是这样的

@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();
     }
}

但是没有用。虽然我指定了 mockSingletondoSomething() 的不同行为,但 mockSingleton 仍然像在 test1 中一样在 test2 中抛出 Exception2。似乎只能指定一次行为。有人能告诉我如何让这里的 doSomething() 有不同的行为吗?

您只调用了一次 Signleton.getInstance - 当 HelperClass 初始化时。这样您就可以始终使用第一次测试中的模拟。要解决这个问题,您可以在每次需要 Singleton.

的实例时调用 getInstance

因此,HelperClass 的代码将是:

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;
    }
}

这样,您将在每个 运行 上获得正确的模拟。