我正在编写一个 junitTest ,它应该测试一个 serverHandler 对象,该对象处理向服务器接收和发送消息。 我通过模拟服务器的套接字并放置我自己的 ObjectInputStream 和 ObjectOutputStream 来做到这一点,以便我能够控制服务器发送的消息。 我无法理解为什么 serverHandler 中的“输出”对象被创建并设置为测试中创建的 ObjectOutputStream,而“输入”对象保持为空并阻塞代码流,直到执行器中的计时器运行并停止线程.
我已经尝试过在outputPipe中写入一些“initialData”,因为我读到ObjectInputStream的构造函数可以阻止代码流,但是这样做我遇到了:java.io.EOFException。问题是,当连接到真正的 SocketServer 时,serverHandler 运行得很好。下面是测试和 serverHandler 的代码实现
public class ServerHandlerTest {
@Test
public void testServerHandler() {
PipedInputStream inputPipe = new PipedInputStream();
PipedOutputStream outputPipe = new PipedOutputStream();
try{
inputPipe.connect(outputPipe);
} catch (Exception e) {
e.printStackTrace();
}
ObjectInputStream input;
ObjectOutputStream output;
try {
output = new ObjectOutputStream(outputPipe);
output.writeObject("Initial Data");
output.flush();
input = new ObjectInputStream(inputPipe);
} catch (Exception e) {
e.printStackTrace();
return;
}
Socket mockServer = mock(Socket.class);
try{
when(mockServer.getOutputStream()).thenReturn(output);
when(mockServer.getInputStream()).thenReturn(input);
} catch (Exception e) {
e.printStackTrace();
}
when(mockServer.getInetAddress()).thenReturn(null);
ServerHandler serverHandler = new ServerHandler(mockServer);
Thread serverHandlerThread = new Thread(serverHandler, "testedServerHandler");
serverHandlerThread.start();
try {
serverHandlerThread.join(); // wait for the serverHandlerThread to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
serverHandler run() 方法:
public void run(){
ExecutorService executor = Executors.newSingleThreadExecutor();
try{
Future<?> future = executor.submit(() -> {
try {
output = new ObjectOutputStream(server.getOutputStream());
input = new ObjectInputStream(server.getInputStream());
System.out.println("Connected to " + server.getInetAddress());
}catch (IOException e) {
try {
System.out.println("Error while creating the input and output streams");
} catch (Exception ex) {
//This is socket, RemoteException should not be thrown
throw new RuntimeException(ex);
}
}
});
future.get(5, TimeUnit.SECONDS);
}catch (TimeoutException e) {
//todo: implementaion of what will if the timers run up
}
有两件事看起来不对:
mockServer.getInputStream()
将返回一个 ObjectInputStream
,然后您的服务器将其包装在另一个 ObjectInputStream
如果解决了这两点,您的测试设置可能如下所示:
@Test
public void testServerHandler() throws IOException, InterruptedException {
PipedInputStream inputPipe = new PipedInputStream();
PipedOutputStream outputPipe = new PipedOutputStream();
inputPipe.connect(outputPipe);
ObjectOutputStream toServer = new ObjectOutputStream(outputPipe);
toServer.writeObject("Initial Data");
toServer.flush();
ByteArrayOutputStream fromServer = new ByteArrayOutputStream();
Socket mockServer = mock(Socket.class);
when(mockServer.getOutputStream()).thenReturn(fromServer);
when(mockServer.getInputStream()).thenReturn(inputPipe);
when(mockServer.getInetAddress()).thenReturn(null);
ServerHandler serverHandler = new ServerHandler(mockServer);
Thread serverHandlerThread = new Thread(serverHandler, "testedServerHandler");
serverHandlerThread.start();
serverHandlerThread.join(); // wait for the serverHandlerThread to finish
}
请注意,我已从测试设置中删除了异常处理。恕我直言,如果测试设置中的某些内容引发异常,则测试设置出现问题并且测试应该失败。实现此目的的最简单方法是让异常在测试方法之外传播。