I was trying out PowerMock, and am trying to mock a private method like so:
expectPrivate(n, "doLogin", anyString(), anyString()).andReturn(true);
That is, I want true
to be returned from doLogin
irrespective of the parameters passed.
The public method which delegates to this private method simply passes-on the arguments. Here is the definition of the class to be mocked:
class N {
public boolean login(String username, String password) {
return doLogin(username, password);
}
private boolean doLogin(String u, String p){
//validate login
//...
//...
return true;
}
}
And this is the test class where I am trying to invoke the mock:
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.createPartialMock;
import static org.powermock.api.easymock.PowerMock.expectPrivate;
import static org.powermock.api.easymock.PowerMock.replay;
import static org.powermock.api.easymock.PowerMock.verify;
import static org.mockito.Matchers.anyString;
import org.easymock.EasyMock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
@RunWith(PowerMockRunner.class)
@PrepareForTest(N.class)
public class NodeAccessorTest {
private String username = "admin";
private String password = "asdf";
@Test
public void testMockLogin() throws Exception {
N n = createPartialMock(N.class,
"doLogin", String.class, String.class);
boolean expected = true;
expectPrivate(n, "doLogin", anyString(), anyString()).andReturn(expected);
replay(n);
boolean actual = n.login("A", "B");
verify(n);
assertEquals("Expected and actual did not match", expected, actual);
}
}
This is the failure trace:
java.lang.AssertionError:
Unexpected method call N.doLogin("A", "B"):
N.doLogin("", ""): expected: 1, actual: 0
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:44)
at org.powermock.api.easymock.internal.invocationcontrol.EasyMockMethodInvocationControl.invoke(EasyMockMethodInvocationControl.java:91)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:124)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:185)
at com.pugmarx.mock.N.doLogin(N.java)
at com.pugmarx.mock.N.login(N.java:60)
So the mocking framework is not happy when specific String
s are passed to the public login()
method, but fine when anyString
is used. Ideally, I would expect that since the call to the private doLogin
is mocked, this should not be the case.
What am I missing?
Both tools are “hiding away” the collaborators in the class under test replacing them with mock objects. The division of work between the two is that Mockito is kind of good for all the standard cases while PowerMock is needed for the harder cases. That includes for example mocking static and private methods.
For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.
PowerMock is an open-source Java framework used for creating a mock object in unit testing. It extends other mocking frameworks such as EasyMock and Mockito to enhance the capabilities.
I had a similar issue and I think your problem can be in the Matchers anyString()
passed by param to PowerMock expectPrivate
method.
Based in your imports, you are using Mockito
Matchers instead EasyMock
Matchers: org.mockito.Matchers.anyString
.
Could you try to changing the Matchers for the next: EasyMock.anyString()
import org.easymock.EasyMock;
...
expectPrivate(n, "doLogin", EasyMock.anyString(), EasyMock.anyString()).andReturn(expected);
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With