2015-10-29 29 views
2

我有Thread它運行在程序運行和民意測驗隊列,並檢查是否有對象,如果是,那麼它的對象上調用方法如何單元測試線程這需要時間來執行動作

這裏驗證碼:

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

這裏是tryLogin方法

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(); 
     } 
} 

現在我的問題是,我要測試的這些服務方法的調用,但是當我運行單元測試他們將無法工作,因爲它需要時間才能達到tryLogin的點,直到那時JUnit失敗。我嘗試使用Thread.sleep(),但我知道這是不正確的做法,因爲它有時會失敗並且有時會通過。

以下是我在我的單元測試

@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)); 
} 

回答

1

該系統是在目前的形式無法驗證:良好的測試質量中有:

  • 容易讓其他程序員undertsand
  • 難以讓其他程序員破解
  • 快速運行

您要測試的邏輯片段是LoginManager.tryLogin,它在您的片段中是私有的。如果你想公開記錄它(測試是一種文檔:他們說明系統應該如何表現),它必須是公開的。

我建議將所有的邏輯移動到新類中的方法:Authentication.attempt()(我建議一個不可變的對象和一個不接受任何參數的方法 - 有人說OO設計中參數的最佳數量爲零)。

現在測試是可行的,我也想你應該擺脫的所有代碼LoginManager.start():只需使用ExecutorService,並提交身份驗證嘗試 - 這種方式,您將有一個更快的程序和更少的代碼來測試,因爲硬(並且棘手)的部分由Java管理。

+0

對於在服務器上接收到的每個登錄請求,您都希望我在run方法內創建Authentication類的對象,並且還可以將Runnable提交給ExecutorService,而不是輪詢隊列? – Sneh

+0

準確。它更簡單,更高效 – Raffaele

相關問題