2013-02-06 130 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:也许你最好先避免套接字。