During unit tests we've encountered a weird error from Mockito
, that at the first glance might look trivial, but after deeper look we can't find why it works like that. Please take a look on the following code and an error that is thrown.
Code
import org.assertj.core.api.Assertions;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
//...
@InjectMocks
@Spy
private MyWebSocket webSocket;
@Mock
private WebSocketUtils webSocketUtils;
@Test
public void myTest() throws IOException {
WebSocketSession session1 = Mockito.mock(WebSocketSession.class);
WebSocketSession session2 = Mockito.mock(WebSocketSession.class);
WebSocketSession session3 = Mockito.mock(WebSocketSession.class);
webSocket.getUserNameWebSocketSessions().put("user1", session1);
webSocket.getUserNameWebSocketSessions().put("user1", session2);
webSocket.getUserNameWebSocketSessions().put("user2", session3);
Mockito.doReturn(new CustomWebSocketMessage<UserSessionInfo>().config(Command.USER_SESSION_INFO).data(new UserSessionInfo()))
.when(webSocket)
.buildUserSessionInfoWebSocketMessage(Mockito.any());
webSocket.onUserPermissionsChange(new UserPermissionsChangedEvent(Collections.singletonList("user1"), this));
ArgumentCaptor<CustomWebSocketMessage> messageCaptor = ArgumentCaptor.forClass(CustomWebSocketMessage.class);
Mockito.verify(webSocketUtils).sendMessageToMultipleUsers(messageCaptor.capture(), Matchers.eq(webSocket.getUserNameWebSocketSessions().get("user1")));
CustomWebSocketMessage message = messageCaptor.getValue();
Assertions.assertThat(message.getMessagePayload().getConfig().getCommand()).isEqualTo(Command.USER_SESSION_INFO.name());
Assertions.assertThat(message.getMessagePayload().getData()).isInstanceOf(UserSessionInfo.class);
}
Error
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded:
-> at ... (Name of the bussines package)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class.
As you can see, the first argument is a captor, the second is Matcher
from Mockito
package. I have no idea why it doesn't work, but what fixed it, was to move getting sessions from Matchers.eq()
method to a variable declaration.
Fixed
Collection<WebSocketSession> sessions = webSocket.getUserNameWebSocketSessions().get("user1");
Mockito.verify(webSocketUtils).sendMessageToMultipleUsers(messageCaptor.capture(), Matchers.eq(sessions));
Can anyone explain me why I had move it to a variable ?