JUnit测试Socket服务端与客户端无响应问题求助
问题根源与解决方案
我立刻发现了导致测试无响应的核心问题:服务端启动逻辑阻塞了测试主线程,导致测试方法根本没有执行的机会。
具体原因分析
你的测试类里有两个@Before注解的方法:
setUp()初始化了客户端和服务端实例serverStart()调用了primaryKeyValueStore.startServer(9000)
而startServer()方法里包含一个while (true)的无限循环,这个循环会一直卡在serverSocket.accept()处等待客户端连接,永远不会返回。由于@Before方法必须执行完成才会进入@Test方法,你的测试主线程被这个死循环彻底卡住,后面的sendMessage()测试代码根本没机会运行。
修复方案:将服务端放在独立线程启动
要解决这个问题,你需要把服务端的启动逻辑放到一个单独的线程中,让测试主线程能够继续执行后续的测试步骤。同时,为了避免测试结束后服务端线程一直占用端口,最好在测试完成后关闭服务端。
修改后的测试类代码如下:
import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Set; public class CollegeClientTest { private CollegeClient collegeClient; private PrimaryKeyValueStore primaryKeyValueStore; private Thread serverThread; @Before public void setUp() { collegeClient = new CollegeClient(); primaryKeyValueStore = new PrimaryKeyValueStore(); } @Before public void serverStart() { // 将服务端启动逻辑放到独立线程中 serverThread = new Thread(() -> primaryKeyValueStore.startServer(9000)); serverThread.start(); // 给服务端一点启动时间,避免客户端连接时服务端还没准备好 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } @Test public void sendMessage() { int port = 9000; Student student = new Student(); student.setUserName("a"); student.setFirstName("aa"); student.setLastName("aaa"); student.setAge(1); student.setMark(100); student.setRestMethod("GET"); Set<Student> employeeSet = collegeClient.sendMessage(student, port); System.out.println("===>> " + employeeSet); } @After public void tearDown() { // 测试结束后中断服务端线程,释放端口 if (serverThread != null && serverThread.isAlive()) { serverThread.interrupt(); } } }
额外注意事项
- 服务端关闭逻辑优化:当前
PrimaryKeyValueStore的startServer()方法里,while(true)循环没有处理线程中断的逻辑,你可以修改循环条件,比如改成while (!Thread.currentThread().isInterrupted()),这样当测试结束调用serverThread.interrupt()时,服务端能够正常退出循环并执行finally块关闭资源。
修改后的startServer()方法关键部分:
try { serverSocket = new ServerSocket(port); // 改成检查线程是否被中断 while (!Thread.currentThread().isInterrupted()) { clientSocket = serverSocket.accept(); // 原有逻辑不变... } } catch (InterruptedException e) { // 捕获中断异常,正常退出 System.out.println("服务端线程被中断,准备关闭"); } catch (Exception e) { // 原有异常处理... } finally { // 原有资源关闭逻辑... }
- 客户端与服务端的对象流交互:确保
Student类实现了Serializable接口,否则对象序列化/反序列化会失败,这也是可能导致交互失败的潜在问题。
内容的提问来源于stack exchange,提问作者Karthikeyan Velmurugan
相关产品推荐
相关产品推荐

