假设以下测试:
public void testSingleton1() {
Mock1 mock1 = PowerMockito.mock(Mock1.class);
Mock2 mock2 = PowerMockito.mock(Mock2.class);
PowerMockito.whenNew(Mock1.class).withNoArguments().thenReturn(mock1);
PowerMockito.when(mock1.getMock2()).thenReturn(mock2);
PowerMockito.when(mock2.method1("A", "B", "C")).thenReturn("D");
Singleton singleton = Singleton.getInstance();
assertEquals("D", singleton.method1("A", "B", "C"));
Mockito.verify(mock1, Mockito.times(1)).getMock2();
Mockito.verify(mock2, Mockito.times(1)).method1("A", "B", "C");
}
public void testSingleton2() {
Mock1 mock1 = PowerMockito.mock(Mock1.class);
Mock2 mock2 = PowerMockito.mock(Mock2.class);
PowerMockito.whenNew(Mock1.class).withNoArguments().thenReturn(mock1);
PowerMockito.when(mock1.getMock2()).thenReturn(mock2);
PowerMockito.when(mock2.method1("B", "C", "D")).thenReturn("F");
Singleton singleton = Singleton.getInstance();
assertEquals("F", singleton.method1("B", "C", "D"));
Mockito.verify(mock1, Mockito.times(1)).getMock2();
Mockito.verify(mock2, Mockito.times(1)).method1("B", "C", "D");
}
第一个测试是成功通过,但第二个测试失败,返回null 我认为这个问题是因为我正在测试一个单例和新的期望( PowerMockito.when(mock2.method1(“B”,“C”,“D”))。thenReturn(“F”); )无效。
PS:当我只运行testSingleton2()时,它正常工作。
答案 0 :(得分:3)
问题是模拟Mock1实例只在testSingleton1()中创建,并在执行Singleton.getInstance()时在Singleton中注入。
在testSingleton2()中,whenNew不起作用,因为单例构造函数不再调用,在这种情况下,会考虑testSingleton2中定义的任何期望。
要解决这个问题,我需要将所有模拟和期望放在一个地方:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Singleton.class, Mock1.class, Mock2.class })
public class SingletonTestCase {
private static Mock1 mock1 = PowerMockito.mock(Mock1.class);
private static Mock2 mock2 = PowerMockito.mock(Mock2.class);
@BeforeClass
public static void beforeClass() {
PowerMockito.whenNew(Mock1.class).withNoArguments().thenReturn(mock1);
PowerMockito.when(mock1.getMock2()).thenReturn(mock2);
PowerMockito.when(mock2.method1("A", "B", "C")).thenReturn("D");
PowerMockito.when(mock2.method1("B", "C", "D")).thenReturn("E");
}
public void testSingleton1() {
Singleton singleton = Singleton.getInstance();
assertEquals("D", singleton.method1("A", "B", "C"));
Mockito.verify(mock1, Mockito.times(1)).getMock2();
Mockito.verify(mock2, Mockito.times(1)).method1("A", "B", "C");
}
public void testSingleton2() {
Singleton singleton = Singleton.getInstance();
assertEquals("E", singleton.method1("B", "C", "D"));
Mockito.verify(mock1, Mockito.times(2)).getMock2();
Mockito.verify(mock2, Mockito.times(2)).method1("B", "C", "D");
}
}
请注意,两项检查均考虑在之前的测试中调用方法
编辑:为避免在模拟上调用累积,您可以在@After方法上使用Mockito.reset(mock)来重置模拟状态。因此,有必要使用@Before再次添加您的期望,例如。
@RunWith(PowerMockRunner.class)
@PrepareForTest({ Singleton.class, Mock1.class, Mock2.class })
public class SingletonTestCase {
private static Mock1 mock1 = PowerMockito.mock(Mock1.class);
private static Mock2 mock2 = PowerMockito.mock(Mock2.class);
@Before
public void before() {
PowerMockito.whenNew(Mock1.class).withNoArguments().thenReturn(mock1);
PowerMockito.when(mock1.getMock2()).thenReturn(mock2);
PowerMockito.when(mock2.method1("A", "B", "C")).thenReturn("D");
PowerMockito.when(mock2.method1("B", "C", "D")).thenReturn("E");
}
@After
public void after() {
Mockito.reset(mock1);
Mockito.reset(mock2);
}
public void testSingleton1() {
Singleton singleton = Singleton.getInstance();
assertEquals("D", singleton.method1("A", "B", "C"));
Mockito.verify(mock1, Mockito.times(1)).getMock2();
Mockito.verify(mock2, Mockito.times(1)).method1("A", "B", "C");
}
public void testSingleton2() {
Singleton singleton = Singleton.getInstance();
assertEquals("E", singleton.method1("B", "C", "D"));
Mockito.verify(mock1, Mockito.times(1)).getMock2();
Mockito.verify(mock2, Mockito.times(1)).method1("B", "C", "D");
}
}
请注意,现在您可以在testSingleton2()上调用Mockito.verify(mock1,Mockito.times(1))和Mockito.verify(mock2,Mockito.times(1))。