package samples.powermockito.junit4.privatemocking;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.exceptions.base.MockitoAssertionError;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import samples.privateandfinal.PrivateFinal;
import samples.privatemocking.PrivateMethodDemo;
import javax.activation.FileDataSource;
import java.io.File;
import java.io.StringReader;
import static org.junit.Assert.*;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.never;
import static org.powermock.api.mockito.PowerMockito.*;
import static org.powermock.api.support.membermodification.MemberMatcher.method;
@RunWith(PowerMockRunner.class)
@PrepareForTest({PrivateMethodDemo.class})
public class PrivateInstanceMockingTest {
@Test
public void expectationsWorkWhenSpyingOnPrivateMethods() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
when(tested, "doSayYear", 12, "test").thenReturn("another");
assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
assertEquals("another", tested.sayYear("test", 12));
verifyPrivate(tested).invoke("doSayYear", 12, "test");
}
@Test
public void expectationsWorkWhenSpyingOnPrivateMethodsUsingDoReturn() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
doReturn("another").when(tested, "doSayYear", 12, "test");
assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
assertEquals("another", tested.sayYear("test", 12));
verifyPrivate(tested).invoke("doSayYear", 12, "test");
}
@Test
public void expectationsWorkWhenSpyingOnPrivateMethodsUsingDoReturnWhenMethodDoesntHaveAnyArguments() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
doReturn("another").when(tested, "sayIt");
assertEquals("another", Whitebox.invokeMethod(tested, "sayIt"));
verifyPrivate(tested).invoke("sayIt");
}
@Test
public void verifyPrivateMethodWhenNoExpectationForTheMethodHasBeenMade() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
}
@Test
public void expectationsWorkWithArgumentMatchersWhenSpyingOnPrivateMethods() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
assertEquals("another", tested.sayYear("Johan", 29));
assertEquals("another", tested.sayYear("test", 12));
verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
verifyPrivate(tested).invoke("doSayYear", 12, "test");
verifyPrivate(tested).invoke("doSayYear", 50, "Temp");
}
@Test
public void errorousVerificationOnPrivateMethodGivesFilteredErrorMessage() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
assertEquals("another", tested.sayYear("Johan", 29));
assertEquals("another", tested.sayYear("test", 12));
try {
verifyPrivate(tested, never()).invoke("doSayYear", 50, "Temp");
fail("Should throw assertion error");
} catch (MockitoAssertionError e) {
assertEquals("\nsamples.privatemocking.PrivateMethodDemo.doSayYear(\n 50,\n \"Temp\"\n);\nNever wanted but invoked .", e
.getMessage());
}
}
@Test(expected = ArrayStoreException.class)
public void expectationsWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
tested.doObjectStuff(new Object());
when(tested, "doObjectInternal", isA(Object.class)).thenThrow(new ArrayStoreException());
tested.doObjectStuff(new Object());
}
@Test
public void answersWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
PrivateMethodDemo tested = spy(new PrivateMethodDemo());
tested.doObjectStuff(new Object());
when(tested, "doObjectInternal", isA(String.class)).thenAnswer(new Answer<Void>() {
private static final long serialVersionUID = 20645008237481667L;
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
assertEquals("Testing", invocation.getArguments()[0]);
return null;
}
});
tested.doObjectStuff(new Object());
tested.doObjectStuff("Testing");
}
@Test
public void spyingOnPrivateFinalMethodsWorksWhenClassIsNotFinal() throws Exception {
PrivateFinal tested = spy(new PrivateFinal());
final String name = "test";
tested.say(name);
assertEquals("Hello " + name, tested.say(name));
when(tested, "sayIt", name).thenReturn("First", "Second");
assertEquals("First", tested.say(name));
assertEquals("Second", tested.say(name));
}
@Test
public void usingMultipleArgumentsOnPrivateMethodWorks() throws Exception {
File file = mock(File.class);
FileDataSource fileDataSource = mock(FileDataSource.class);
StringReader expected = new StringReader("Some string");
PrivateMethodDemo tested = mock(PrivateMethodDemo.class);
doReturn(expected).when(tested, method(PrivateMethodDemo.class, "createReader", File.class, FileDataSource.class)).withArguments(file, fileDataSource);
StringReader actual = Whitebox.invokeMethod(tested, "createReader", file, fileDataSource);
assertSame(expected, actual);
}
}