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

JUnit中使用Jetty Stub服务器遇java.net.ConnectException问题求助

JUnit中使用Jetty 6.1.26 Stub服务器时出现连接拒绝异常,浏览器需等测试结束才响应

我在JUnit测试中使用org.mortbay.jetty:jetty:6.1.26搭建Stub服务器,期望返回预设内容,但执行时抛出java.net.ConnectException: Connection refused: no further information异常。另外,测试期间从浏览器访问Stub端点不会立即返回响应,要等所有JUnit执行完成、Jetty服务器关闭后才会返回预期内容,同时应用日志中出现Socket关闭异常。查了相关帖子没解决,求帮助。


详细信息

应用核心代码

应用通过CompletableFuture链式调用获取外部数据、解析并保存,实际环境运行正常:

HTTPUtilities.performGet(uri)
    .thenApply(HTTPUtilities::httpResponseToReader)
    .thenApply(reader -> parseContent(reader, id))
    .thenAccept(idDetailsList -> idRepository.saveAll(idDetailsList))
    .whenComplete((resp, err) -> {
        if (err == null) {
            log.info("Data for {} is successfully saved", id);
        } else {
            log.error("Exception encountered for URI {} / id : {}. Message: -> {} ", uri, id, err.getMessage());
        }
    });

待Stub的静态方法HTTPUtilities.performGet

该方法通过线程池执行HTTP请求,实际环境正常,测试环境执行出错:

HttpUriRequest request = RequestBuilder.get()
        .setUri(uri)
        .setHeader(HttpHeaders.ACCEPT, HEADER_ACCEPT_CONSTANT)
        .setHeader(HttpHeaders.USER_AGENT, HEADER_USER_AGENT_CONSTANT)
        .build();

CompletableFuture<HttpResponse> resp = new CompletableFuture<>();
executorService.execute(() -> {
    try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(config).build();
         CloseableHttpResponse response = httpclient.execute(request)) {
            resp.complete(response);
            log.info("Successfully returning response for URL: {}", uri);
    } catch (NullPointerException ex) {
        log.error("NullPointerException encountered when performing GET against URL {} with message {}", uri, ex.getCause());
        resp.completeExceptionally(ex);
    } catch (IOException ex) {
        log.error("IOException encountered when performing GET against URL {} with message {}", uri, ex.getCause());
        resp.completeExceptionally(ex);
    }
});

return resp;

异常栈信息

代码执行到CloseableHttpResponse response = httpclient.execute(request)时抛出以下异常:

java.net.ConnectException: Connection refused: no further information
    at java.base/sun.nio.ch.Net.pollConnect(Native Method)
    at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
    at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542)
    at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
    at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
    at java.base/java.net.Socket.connect(Socket.java:633)
    at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)

JUnit测试代码

@ExtendWith(MockitoExtension.class)
public class IdRetreieveAndSaveTest {

    @InjectMocks
    UpdateIdData updateIdData;

    @BeforeAll
    static void initial() throws Exception {

        //Stub to replace actual call
        Server server = new Server(stubbedPort);
        Context contentOkContext = new Context(server, stubbedContext);
        contentOkContext.setHandler(new HttpCustomHandler());
        server.setStopAtShutdown(true);
        server.start();

    }
    
    @Test
    void updateIdDataTest() {
    
        List<IdData> resp = new ArrayList<>();
        updateIdData.invokeHttpAndSave(id);
        assertEquals(100, resp.size());
    
    }

}

Jetty Handler代码

public class HttpCustomHandler extends AbstractHandler {

    @Override
    public void handle(String s, HttpServletRequest httpServletRequest, HttpServletResponse response, int i) throws IOException {
        OutputStream out = response.getOutputStream();
        try (ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer()) {
            writer.write(codeThatReturnsSampleDataFromExternalClient());
            writer.flush();
            response.setIntHeader(HttpHeaders.CONTENT_LENGTH, writer.size());
            writer.writeTo(out);
            out.flush();
        };
    }

}

端口监听验证

调试时执行netstat -ano | Select-String -pattern "65500",确认端口处于监听状态,测试结束后监听记录消失:

netstat -ano | Select-String -pattern "65500"

  TCP    0.0.0.0:65500          0.0.0.0:0              LISTENING       27448
  TCP    [::]:65500             [::]:0                 LISTENING       27448

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 15:55:18