The problem is that the mock a Mock1 instance is created only in testSingleton1() and injected in the Singleton when Singleton.getInstance() is executed.
In testSingleton2() the whenNew doesn't work since the singleton constructor is not call anymore, in this case any expectations defined in testSingleton2 is taken into consideration.
To solve that i need to put all mocks and their expectations in one place:
@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");
}
}
Notice that both checks consider calls to methods in previous tests
EDIT: To avoid the accumulation of calls on mocks you can use Mockito.reset(mock) on @After method to reset the mock state. It is therefore necessary to add your expectations again using an @Before, for example.
@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");
}
}
Notice that now you can call Mockito.verify(mock1, Mockito.times(1)) and Mockito.verify(mock2, Mockito.times(1)) on testSingleton2().