2013-02-06 132 views
3

我有一個類是套接字客戶端,我試圖單元測試它的方法。測試要求我在每次測試之前啓動一個套接字服務器,所以我使用:java中的單元測試套接字

@Before 
public void setUp() { 
    if (myServerSocket == null) { 
    Thread myThread = new Thread() { 
     public void run() { 
      DataInputStream dis = null; 
      DataOutputStream dos = null; 
      try { 
       ServerSocket myServer = new ServerSocket(port); 
       myServerSocket = myServer.accept(); 
       dis = new DataInputStream(myServerSocket.getInputStream()); 
       dos = new DataOutputStream(myServerSocket.getOutputStream()); 
       byte[] bytes = new byte[10]; 
       dis.read(bytes); 
       boolean breakLoop = false; 
       do { 
        if (new String(bytes).length() != 0) { 
         dos.writeBytes(serverMessage + "\n"); 
         dos.flush(); 
         breakLoop = true; 
         dos.writeBytes("</BroadsoftDocument>" + "\n"); 
         dos.flush(); 
        } 
       } while (!breakLoop); 
      } 
      catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    myThread.start(); 
    } 
} 

每次測試後,我試圖關閉服務器套接字,所以我可以重新打開服務器套接字下次測試:

@After 
public void tearDown() throws IOException, BroadsoftSocketException { 
    System.out.println("@After"); 
    if (myServerSocket != null) { 
     myServerSocket.close(); 
     myServerSocket = null; 
      try { 
       Thread.sleep(5000); 
      } 
      catch (InterruptedException e) { 
       // do nothing. 
      } 
    } 
} 

但是,在第二次測試開始的每次測試之前,我都會得到「java.net.BindException:已經使用的地址:JVM_Bind」。我意識到我正在嘗試爲每個測試使用相同的端口,但不應該關閉套接字釋放端口?

+2

您確實需要連接到真實的套接字來測試您的代碼嗎?要測試套接字下游的代碼,可以將其抽象出來,以便傳入實際寫入/讀取單元測試的'InputStream'和'OutputStream'。 – SimonC

+0

我以前在單元測試中見過套接字。它並沒有結束 - 很多隨機失敗。特別是延遲加入睡眠(5000)後,因爲不同人的機器在關閉插座時速度會更慢。 有沒有辦法重構類,以便它的「SocketClient」部分與其「可測試」邏輯部分分離?測試底層的Java Socket代碼沒有什麼好處 - 我們知道這很有用。你只想單元測試生成消息的代碼位。 –

回答

4

當您試圖重新連接它時,很可能您的套接字仍處於TIME_WAIT狀態。我會建議嘲笑這樣的外部依賴,但如果你真的發現自己想繼續使用真正的套接字,然後嘗試設置重新綁定選項。在您的設置功能中,不要使用ServerSocket myServer = new ServerSocket(port);

final ServerSocket myServer = new ServerSocket(); 
myServer.setReuseAddress(true); 
myServer.bind(new java.net.InetSocketAddress(port)); 
+0

這樣做了,謝謝! – badgerduke

1
  1. 你已經在「setUp」中關閉了你的serversocket,你真的應該在finally塊中做。
  2. 該端口可能無法立即釋放。您可以通過將ServerSocket的reuseAdress設置爲true來避免這種情況。見setReuseAddress

而我第二個SimonC:也許你最好先避免套接字。