测试Java套接字
问题内容:
我正在开发网络应用程序,我想正确进行单元测试。这次我们会做的,你知道吗?:)
我在测试网络连接时遇到了麻烦。
在我的应用程序中,我使用plain java.net.Socket
。
例如:
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Message {
byte[] payload;
public Message(byte[] payload) {
this.payload = payload;
}
public boolean sendTo(String hostname, int port) {
boolean sent = false;
try {
Socket socket = new Socket(hostname, port);
OutputStream out = socket.getOutputStream();
out.write(payload);
socket.close();
sent = true;
} catch (UnknownHostException e) {
} catch (IOException e) {
}
return sent;
}
}
我读过有关模拟的内容,但不确定如何应用。
问题答案:
如果要测试代码,请执行以下操作。
首先,重构代码,以便Socket
不会在要测试的方法中直接实例化。下面的示例显示了我可以想到的最小更改。将来的更改可能会将Socket
创建过程排除在一个完全独立的类之外,但是我喜欢一些小步骤,而且我不喜欢在未经测试的代码上进行大的更改。
public boolean sendTo(String hostname, int port) {
boolean sent = false;
try {
Socket socket = createSocket();
OutputStream out = socket.getOutputStream();
out.write(payload);
socket.close();
sent = true;
} catch (UnknownHostException e) {
// TODO
} catch (IOException e) {
// TODO
}
return sent;
}
protected Socket createSocket() {
return new Socket();
}
既然套接字创建逻辑不在您要测试的方法之外,您就可以开始进行模拟并加入套接字的创建中。
public class MessageTest {
@Test
public void testSimplePayload() () {
byte[] emptyPayload = new byte[1001];
// Using Mockito
final Socket socket = mock(Socket.class);
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
when(socket.getOutputStream()).thenReturn(byteArrayOutputStream);
Message text = new Message(emptyPayload) {
@Override
protected Socket createSocket() {
return socket;
}
};
Assert.assertTrue("Message sent successfully", text.sendTo("localhost", "1234"));
Assert.assertEquals("whatever you wanted to send".getBytes(), byteArrayOutputStream.toByteArray());
}
}
在要测试的单元上覆盖单个方法对于测试确实有用,尤其是在具有可怕依赖关系的丑陋代码中。显然,最好的解决方案是解决依赖关系(在这种情况下,我认为a
Message
不依赖a Socket
,也许会Messager
像glowcoder所建议的那样有一个接口),但是最好以尽可能小的步骤迈向解决方案。