jeudi 29 octobre 2015

How to Unit-Test Thread which takes time to perform action

I have Thread which runs while the program runs and polls a queue and check whether it has object and if yes then it calls method on the object

Here is the code :

while(isRunning){
        synchronized (loginQueue) {
            if(loginQueue.peek() != null) {
                Object[] loginObjectWithConnection = loginQueue.poll();
                tryLogin(loginObjectWithConnection);
            }
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

Here is the tryLogin method

private void tryLogin(Object[] loginObjectWithConnection) {
        LoginPacket packet = (LoginPacket)loginObjectWithConnection[0];
        Connection connection = (Connection)loginObjectWithConnection[1];

        try {
            if(playerDataService.arevalidCredentials(packet.getUserName(), packet.getPassword())) {

                if(!playerDataService.isPlayerBanned(packet.getUserName())){ //Player exists in the system

                    communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.PLAYER_BANNED));

                } else{ //Player is not banned

                }
            } else { // Player does not exist
                communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.INVALID_USER));
            }
        } catch (SQLException e) {
            communicationService.sendTCP(connection, packetFactory.makeLoginFailurePacket(StringConstants.SERVER_ERROR));
            e.printStackTrace();
        }
}

Now my problem is that I want to test the invocations of these service methods but when I run the unit tests they won't work as it takes time to reach the point of tryLogin and till then JUnit fails. I tries using Thread.sleep() but I know it is not the right way to do it as it fails sometimes and pass sometimes.

Here is what I have in my Unit Test

@Test
public void theExpectedMessageShouldBeSentIfUserIsBanned() throws InterruptedException, SQLException {
    //Arrange
    when(moqLoginQueue.peek()).thenReturn(object);
    when(moqLoginQueue.poll()).thenReturn(object);
    LoginFailurePacket packet = new LoginFailurePacket(StringConstants.PLAYER_BANNED);
    when(moqPacketFactory.makeLoginFailurePacket(StringConstants.PLAYER_BANNED)).thenReturn(packet);
    when(moqPlayerDataService.arevalidCredentials(anyString(), anyString())).thenReturn(true);
    when(moqPlayerDataService.isPlayerBanned(anyString())).thenReturn(true);

    //Act
    loginManager.start();
    Thread.sleep(10); //Dirty hack -.-

    //Assert
    verify(moqCommunicationService).sendTCP(any(Connection.class), eq(packet));
}

Aucun commentaire:

Enregistrer un commentaire