You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
        }
    }
}

额外注意事项

  1. 服务端关闭逻辑优化:当前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 {
    // 原有资源关闭逻辑...
}
  1. 客户端与服务端的对象流交互:确保Student类实现了Serializable接口,否则对象序列化/反序列化会失败,这也是可能导致交互失败的潜在问题。

内容的提问来源于stack exchange,提问作者Karthikeyan Velmurugan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:19:13