anyString() v/s anyString() in Mocking frameworks
So I was trying out mocking frameworks for the first time a few days ago, and there's an interesting observation: even though EasyMock, PowerMock, and Mockito and said to be brothers-in-arms, there are a few nuances to take care of. One of them is the following.
There are convenience methods (called matchers
) provided by both Mockito and EasyMock to define a message signature that can accept any value of a given parameter type. It is claimed, that these any implementations (e.g. anyObject, anyString, etc.) are interchangeable, but that does not seem to be the case.
Consider a very simple scenario, where one would want to mock a login() implementation. That is to say, success (true
in this case) must be returned, regardless of the parameters passed.
class N {
public boolean login(String username, String password) {
return doLogin(username, password);
}
private boolean doLogin(String u, String p){ //validate login //... //... return true; } }
Now that the method is defined, let's take a look at the test case where we would mock is call.
@Test
public void testMockLogin() throws Exception {
// mocking only specific methods
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("foo", "bar");
verify(n);
assertEquals("Expected and actual did not match", expected, actual);
}
Easy, peasy! Except for line no. 7, where anyString()
is used via the import org.mockito.Matchers.anyString
, causing the following exception:
java.lang.AssertionError:
Unexpected method call N.doLogin("foo", "bar"):
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)
...
The same test case passes when the anyString()
implementation of Mockito is replaced by the implementation provided by EasyMock (via org.easymock.EasyMock.anyString
). If we dig a bit, we realize that one of the reasons could be that EasyMock.anyString
returns null
, as against the empty string returned by mockit.Matchers.anyString
.
[Thank you for troig from the wonderful StackOverflow community for helping me on this query.]