简体   繁体   中英

What is the recommended way to unit test code that uses UDP sockets?

After a bit of searching, I have not come across a well-defined solution to unit (Junit) testing Java(or any!) code that includes a UDP socket. I have a piece of Java code that opens up a UDP socket and sends some encoded data in. The test I am writing will make sure that the data going in is the "same" data coming out. Therefore, I will need to send one one side, and receive on the other. Due to the nature of UDP sockets, one can not open up multiple sockets listening in on the same port number. If someone tries to do so, they will hit this exception:

java.net.BindException: Address already in use: Cannot bind

As far as I understand, sending and receiving over the same port via UDP requires the same socket to be used for both function. Please correct me if I am wrong.

I have two ideas at the moment:

  1. Use reflection to expose the private member datagramSocketOut, and then set the reuse flag to true. At which point, I would copy(& reuse) this socket to a datagramSocketIn and receive from this new end. In my eyes, this seems rather janky and just plain smells bad.

  2. Refactor my code to no longer create a new socket internaly, but instead be passed one in externally. This willremove the responsibility of creating the socket from the code I am testing, and allow the same socket to be reused for testing.

Is one of these two the reccomended method to unit testing that involves UDP sockets? Or is there another approach I am missing?

Edit: For the sake of anyone with the same misinterpretation as I had, they should know that a UDP socket can be null constructed DatagramSocket ds = new DatagramSocket(); and therefore not binded to a port on instantiation. This avoids having two UDP sockets listening on the same port. For the sake of brevity, here is a code snippet that avoids the problem I described.

socketOut = new DatagramSocket(PORT, addressOut);   
socketIn = new DatagramSocket(PORT+1); 
socketOut.send(new DatagramPacket(Payload, Payload.length, addressOut, PORT+1 )); 
socketIn.receive(new DatagramPacket(bufferIn, bufferIn.length));

The code you're testing should have two parameters for port, one for a local port to bind to and one for a remote port to send to. That way, both endpoints can live on the same machine. Then in your unit test code, you bind to the "remote" port and send to the "local" port.

For example, your class is set to bind on port 7000 and send on port 7001. So outgoing packets will have a source port of 7000 and a destination port of 7001. Your unit test code would then bind on port 7001 and send on port 7000.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM