I\'m (still) trying to check if bar(Alpha, Baz)
called bar(Xray, Baz)
using PowerMockito (as bar(Xray, Baz)
is private
) - wit
When setting the expectations, we have to use the exact argument matcher. In your case, it is Matchers.any(Xray.class), Matchers.any(Baz.class)
I have modified your code as below and also added assert statement on output object of your test method.
@RunWith(PowerMockRunner.class)
//@PrepareOnlyThisForTest(Foo.class) // we aren't looking at the byte code, I think
public class FooTest {
@Test
public void testBar_callsBarWithXray() throws Exception {
Baz baz = new Baz(); //POJOs
Alpha alpha = new Alpha();
alpha.set(new Xray());
Foo foo = new Foo();
Foo stub = PowerMockito.spy(foo); // using Mockito, as it's neither final nor "not spyable"
// NPE at org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl.addAnswersForStubbing(PowerMockitoStubberImpl.java:67)
PowerMockito.doReturn("ok").when(stub, "bar", Matchers.any(Xray.class), Matchers.any(Baz.class));
String res = stub.bar(alpha, baz);
Assert.assertEquals("ok", res);
//Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class));
// Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
}
}
Observation : when calling verify methods, we have to pass stub object not actual object because we set expectations on stub object. As I added assert statements to test the method, you don't have to verify on the stub whether it is working properly or not.
ADDED: I added sysout statements in both public & private 'bar' methods and when I tested again, I see that sysout statement of public bar method is not printed. It means the above code mocked public method only but not private method.
To mock private 'bar' method, I tried with another way of mocking using MemberMatcher.method which worked perfectly.
import org.powermock.api.support.membermodification.MemberMatcher;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Foo.class) // we need this
public class FooTest {
@Test
public void testBar_callsBarWithXray() throws Exception {
Baz baz = new Baz(); //POJOs
Alpha alpha = new Alpha();
alpha.set(new Xray());
Foo stub = PowerMockito.spy(new Foo());
PowerMockito.doReturn("ok")
.when(stub,
MemberMatcher.method(Foo.class,
"bar",
Xray.class, Baz.class))
.withArguments(Matchers.any(Xray.class), Matchers.any(Baz.class));
String res = stub.bar(alpha, baz);
Assert.assertEquals("ok", res);
//Testing if bar(Xray, Baz) was called by bar(Alpha, Baz)
PowerMockito.verifyPrivate(stub).invoke("bar", Matchers.any(Xray.class), Matchers.any(Baz.class));
// Mockito's equivalent for a public method: verify(stub, times(1)).bar(any(Xray.class), any(Baz.class));
}
output : public bar
Test method is also passed. Below are foo methods having sysouts.
private String bar(Xray xray, Baz baz) {
System.out.println("private bar");
return "Xray";
}
public String bar(Alpha alpha, Baz baz) {
System.out.println("public bar");
if(alpha.get() instanceof Xray) {
return bar((Xray)alpha.get(), baz);
} else if(alpha.get() instanceof Zulu) {
return bar((Zulu)alpha.get(), baz);
} else {
return null;
}
}