Skip to content

Commit 7dea7c8

Browse files
author
dyc_98
committed
fix unit tests fail for http client timeout in offline environment (#636)
1 parent 06fdc71 commit 7dea7c8

File tree

4 files changed

+101
-61
lines changed

4 files changed

+101
-61
lines changed

mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
package io.modelcontextprotocol.server;
66

7+
import java.io.IOException;
78
import java.net.URI;
89
import java.net.http.HttpClient;
910
import java.net.http.HttpRequest;
1011
import java.net.http.HttpResponse;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
1114
import java.time.Duration;
1215
import java.util.List;
1316
import java.util.Map;
@@ -45,6 +48,7 @@
4548
import io.modelcontextprotocol.spec.McpSchema.Tool;
4649
import io.modelcontextprotocol.util.Utils;
4750
import net.javacrumbs.jsonunit.core.Option;
51+
import org.junit.jupiter.api.BeforeAll;
4852
import org.junit.jupiter.params.ParameterizedTest;
4953
import org.junit.jupiter.params.provider.MethodSource;
5054
import org.junit.jupiter.params.provider.ValueSource;
@@ -58,18 +62,30 @@
5862
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
5963
import static org.assertj.core.api.Assertions.assertWith;
6064
import static org.awaitility.Awaitility.await;
65+
import static org.mockito.ArgumentMatchers.any;
6166
import static org.mockito.Mockito.mock;
67+
import static org.mockito.Mockito.when;
6268

6369
public abstract class AbstractMcpClientServerIntegrationTests {
6470

6571
protected ConcurrentHashMap<String, McpClient.SyncSpec> clientBuilders = new ConcurrentHashMap<>();
6672

73+
protected static HttpClient mockClient = mock(HttpClient.class);
74+
6775
abstract protected void prepareClients(int port, String mcpEndpoint);
6876

6977
abstract protected McpServer.AsyncSpecification<?> prepareAsyncServerBuilder();
7078

7179
abstract protected McpServer.SyncSpecification<?> prepareSyncServerBuilder();
7280

81+
@BeforeAll
82+
protected static void initMockClient() throws IOException, InterruptedException {
83+
HttpResponse<String> mockResponse = mock(HttpResponse.class);
84+
when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath()));
85+
when(mockResponse.statusCode()).thenReturn(200);
86+
when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse);
87+
}
88+
7389
@ParameterizedTest(name = "{0} : {displayName} ")
7490
@MethodSource("clientsForTesting")
7591
void simple(String clientType) {
@@ -774,12 +790,11 @@ void testToolCallSuccess(String clientType) {
774790
.callHandler((exchange, request) -> {
775791

776792
try {
777-
HttpResponse<String> response = HttpClient.newHttpClient()
778-
.send(HttpRequest.newBuilder()
779-
.uri(URI.create(
780-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
781-
.GET()
782-
.build(), HttpResponse.BodyHandlers.ofString());
793+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
794+
.uri(URI.create(
795+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
796+
.GET()
797+
.build(), HttpResponse.BodyHandlers.ofString());
783798
String responseBody = response.body();
784799
responseBodyIsNullOrBlank.set(!Utils.hasText(responseBody));
785800
}
@@ -923,12 +938,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
923938
.callHandler((exchange, request) -> {
924939
// perform a blocking call to a remote service
925940
try {
926-
HttpResponse<String> response = HttpClient.newHttpClient()
927-
.send(HttpRequest.newBuilder()
928-
.uri(URI.create(
929-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
930-
.GET()
931-
.build(), HttpResponse.BodyHandlers.ofString());
941+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
942+
.uri(URI.create(
943+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
944+
.GET()
945+
.build(), HttpResponse.BodyHandlers.ofString());
932946
String responseBody = response.body();
933947
assertThat(responseBody).isNotBlank();
934948
}
@@ -948,12 +962,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
948962
try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> {
949963
// perform a blocking call to a remote service
950964
try {
951-
HttpResponse<String> response = HttpClient.newHttpClient()
952-
.send(HttpRequest.newBuilder()
953-
.uri(URI.create(
954-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
955-
.GET()
956-
.build(), HttpResponse.BodyHandlers.ofString());
965+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
966+
.uri(URI.create(
967+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
968+
.GET()
969+
.build(), HttpResponse.BodyHandlers.ofString());
957970
String responseBody = response.body();
958971
assertThat(responseBody).isNotBlank();
959972
toolsRef.set(toolsUpdate);

mcp-core/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343

4444
import org.springframework.mock.web.MockHttpServletRequest;
4545
import org.springframework.mock.web.MockHttpServletResponse;
46-
import org.springframework.web.client.RestClient;
4746

4847
import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.APPLICATION_JSON;
4948
import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.TEXT_EVENT_STREAM;
@@ -122,12 +121,14 @@ void testToolCallSuccess(String clientType) {
122121
Tool.builder().name("tool1").title("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build(),
123122
(transportContext, request) -> {
124123
// perform a blocking call to a remote service
125-
String response = RestClient.create()
126-
.get()
127-
.uri("https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")
128-
.retrieve()
129-
.body(String.class);
124+
String response = "{\"result\":\"test result\"}";
130125
assertThat(response).isNotBlank();
126+
try {
127+
Thread.sleep(1000L);
128+
}
129+
catch (InterruptedException e) {
130+
throw new RuntimeException(e);
131+
}
131132
return callResponse;
132133
});
133134

mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
package io.modelcontextprotocol;
66

7+
import java.io.IOException;
78
import java.net.URI;
89
import java.net.http.HttpClient;
910
import java.net.http.HttpRequest;
1011
import java.net.http.HttpResponse;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
1114
import java.time.Duration;
1215
import java.util.List;
1316
import java.util.Map;
@@ -49,6 +52,7 @@
4952
import io.modelcontextprotocol.spec.McpSchema.Tool;
5053
import io.modelcontextprotocol.util.Utils;
5154
import net.javacrumbs.jsonunit.core.Option;
55+
import org.junit.jupiter.api.BeforeAll;
5256
import org.junit.jupiter.params.ParameterizedTest;
5357
import org.junit.jupiter.params.provider.MethodSource;
5458
import org.junit.jupiter.params.provider.ValueSource;
@@ -62,18 +66,30 @@
6266
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
6367
import static org.assertj.core.api.Assertions.assertWith;
6468
import static org.awaitility.Awaitility.await;
69+
import static org.mockito.ArgumentMatchers.any;
6570
import static org.mockito.Mockito.mock;
71+
import static org.mockito.Mockito.when;
6672

6773
public abstract class AbstractMcpClientServerIntegrationTests {
6874

6975
protected ConcurrentHashMap<String, McpClient.SyncSpec> clientBuilders = new ConcurrentHashMap<>();
7076

77+
protected static HttpClient mockClient = mock(HttpClient.class);
78+
7179
abstract protected void prepareClients(int port, String mcpEndpoint);
7280

7381
abstract protected McpServer.AsyncSpecification<?> prepareAsyncServerBuilder();
7482

7583
abstract protected McpServer.SyncSpecification<?> prepareSyncServerBuilder();
7684

85+
@BeforeAll
86+
protected static void initMockClient() throws IOException, InterruptedException {
87+
HttpResponse<String> mockResponse = mock(HttpResponse.class);
88+
when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath()));
89+
when(mockResponse.statusCode()).thenReturn(200);
90+
when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse);
91+
}
92+
7793
@ParameterizedTest(name = "{0} : {displayName} ")
7894
@MethodSource("clientsForTesting")
7995
void simple(String clientType) {
@@ -778,12 +794,11 @@ void testToolCallSuccess(String clientType) {
778794
.callHandler((exchange, request) -> {
779795

780796
try {
781-
HttpResponse<String> response = HttpClient.newHttpClient()
782-
.send(HttpRequest.newBuilder()
783-
.uri(URI.create(
784-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
785-
.GET()
786-
.build(), HttpResponse.BodyHandlers.ofString());
797+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
798+
.uri(URI.create(
799+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
800+
.GET()
801+
.build(), HttpResponse.BodyHandlers.ofString());
787802
String responseBody = response.body();
788803
responseBodyIsNullOrBlank.set(!Utils.hasText(responseBody));
789804
}
@@ -927,12 +942,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
927942
.callHandler((exchange, request) -> {
928943
// perform a blocking call to a remote service
929944
try {
930-
HttpResponse<String> response = HttpClient.newHttpClient()
931-
.send(HttpRequest.newBuilder()
932-
.uri(URI.create(
933-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
934-
.GET()
935-
.build(), HttpResponse.BodyHandlers.ofString());
945+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
946+
.uri(URI.create(
947+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
948+
.GET()
949+
.build(), HttpResponse.BodyHandlers.ofString());
936950
String responseBody = response.body();
937951
assertThat(responseBody).isNotBlank();
938952
}
@@ -952,12 +966,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
952966
try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> {
953967
// perform a blocking call to a remote service
954968
try {
955-
HttpResponse<String> response = HttpClient.newHttpClient()
956-
.send(HttpRequest.newBuilder()
957-
.uri(URI.create(
958-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
959-
.GET()
960-
.build(), HttpResponse.BodyHandlers.ofString());
969+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
970+
.uri(URI.create(
971+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
972+
.GET()
973+
.build(), HttpResponse.BodyHandlers.ofString());
961974
String responseBody = response.body();
962975
assertThat(responseBody).isNotBlank();
963976
toolsRef.set(toolsUpdate);

mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@
44

55
package io.modelcontextprotocol;
66

7+
import java.io.IOException;
78
import java.net.URI;
89
import java.net.http.HttpClient;
910
import java.net.http.HttpRequest;
1011
import java.net.http.HttpResponse;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
1114
import java.time.Duration;
1215
import java.util.List;
1316
import java.util.Map;
@@ -27,9 +30,9 @@
2730
import io.modelcontextprotocol.spec.McpSchema.TextContent;
2831
import io.modelcontextprotocol.spec.McpSchema.Tool;
2932
import net.javacrumbs.jsonunit.core.Option;
33+
import org.junit.jupiter.api.BeforeAll;
3034
import org.junit.jupiter.params.ParameterizedTest;
3135
import org.junit.jupiter.params.provider.MethodSource;
32-
import org.junit.jupiter.params.provider.ValueSource;
3336
import reactor.core.publisher.Mono;
3437

3538
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
@@ -38,17 +41,30 @@
3841
import static org.assertj.core.api.Assertions.assertThat;
3942
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
4043
import static org.awaitility.Awaitility.await;
44+
import static org.mockito.ArgumentMatchers.any;
45+
import static org.mockito.Mockito.mock;
46+
import static org.mockito.Mockito.when;
4147

4248
public abstract class AbstractStatelessIntegrationTests {
4349

4450
protected ConcurrentHashMap<String, McpClient.SyncSpec> clientBuilders = new ConcurrentHashMap<>();
4551

52+
protected static HttpClient mockClient = mock(HttpClient.class);
53+
4654
abstract protected void prepareClients(int port, String mcpEndpoint);
4755

4856
abstract protected StatelessAsyncSpecification prepareAsyncServerBuilder();
4957

5058
abstract protected StatelessSyncSpecification prepareSyncServerBuilder();
5159

60+
@BeforeAll
61+
protected static void initMockClient() throws IOException, InterruptedException {
62+
HttpResponse<String> mockResponse = mock(HttpResponse.class);
63+
when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath()));
64+
when(mockResponse.statusCode()).thenReturn(200);
65+
when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse);
66+
}
67+
5268
@ParameterizedTest(name = "{0} : {displayName} ")
5369
@MethodSource("clientsForTesting")
5470
void simple(String clientType) {
@@ -89,12 +105,11 @@ void testToolCallSuccess(String clientType) {
89105
.callHandler((ctx, request) -> {
90106

91107
try {
92-
HttpResponse<String> response = HttpClient.newHttpClient()
93-
.send(HttpRequest.newBuilder()
94-
.uri(URI.create(
95-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
96-
.GET()
97-
.build(), HttpResponse.BodyHandlers.ofString());
108+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
109+
.uri(URI.create(
110+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
111+
.GET()
112+
.build(), HttpResponse.BodyHandlers.ofString());
98113
String responseBody = response.body();
99114
assertThat(responseBody).isNotBlank();
100115
}
@@ -177,12 +192,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
177192
.callHandler((ctx, request) -> {
178193
// perform a blocking call to a remote service
179194
try {
180-
HttpResponse<String> response = HttpClient.newHttpClient()
181-
.send(HttpRequest.newBuilder()
182-
.uri(URI.create(
183-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
184-
.GET()
185-
.build(), HttpResponse.BodyHandlers.ofString());
195+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
196+
.uri(URI.create(
197+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
198+
.GET()
199+
.build(), HttpResponse.BodyHandlers.ofString());
186200
String responseBody = response.body();
187201
assertThat(responseBody).isNotBlank();
188202
}
@@ -202,12 +216,11 @@ void testToolListChangeHandlingSuccess(String clientType) {
202216
try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> {
203217
// perform a blocking call to a remote service
204218
try {
205-
HttpResponse<String> response = HttpClient.newHttpClient()
206-
.send(HttpRequest.newBuilder()
207-
.uri(URI.create(
208-
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
209-
.GET()
210-
.build(), HttpResponse.BodyHandlers.ofString());
219+
HttpResponse<String> response = mockClient.send(HttpRequest.newBuilder()
220+
.uri(URI.create(
221+
"https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md"))
222+
.GET()
223+
.build(), HttpResponse.BodyHandlers.ofString());
211224
String responseBody = response.body();
212225
assertThat(responseBody).isNotBlank();
213226
}

0 commit comments

Comments
 (0)