diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java index 1f5387f37..082086f4c 100644 --- a/mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java +++ b/mcp-core/src/test/java/io/modelcontextprotocol/server/AbstractMcpClientServerIntegrationTests.java @@ -4,10 +4,13 @@ package io.modelcontextprotocol.server; +import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; import java.util.List; import java.util.Map; @@ -45,6 +48,7 @@ import io.modelcontextprotocol.spec.McpSchema.Tool; import io.modelcontextprotocol.util.Utils; import net.javacrumbs.jsonunit.core.Option; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; @@ -58,18 +62,30 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertWith; import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public abstract class AbstractMcpClientServerIntegrationTests { protected ConcurrentHashMap clientBuilders = new ConcurrentHashMap<>(); + protected static HttpClient mockClient = mock(HttpClient.class); + abstract protected void prepareClients(int port, String mcpEndpoint); abstract protected McpServer.AsyncSpecification prepareAsyncServerBuilder(); abstract protected McpServer.SyncSpecification prepareSyncServerBuilder(); + @BeforeAll + protected static void initMockClient() throws IOException, InterruptedException { + HttpResponse mockResponse = mock(HttpResponse.class); + when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath())); + when(mockResponse.statusCode()).thenReturn(200); + when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse); + } + @ParameterizedTest(name = "{0} : {displayName} ") @MethodSource("clientsForTesting") void simple(String clientType) { @@ -774,12 +790,11 @@ void testToolCallSuccess(String clientType) { .callHandler((exchange, request) -> { try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); responseBodyIsNullOrBlank.set(!Utils.hasText(responseBody)); } @@ -923,12 +938,11 @@ void testToolListChangeHandlingSuccess(String clientType) { .callHandler((exchange, request) -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); } @@ -948,12 +962,11 @@ void testToolListChangeHandlingSuccess(String clientType) { try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); toolsRef.set(toolsUpdate); diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java index 491c2d4ed..d8131b508 100644 --- a/mcp-core/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java +++ b/mcp-core/src/test/java/io/modelcontextprotocol/server/HttpServletStatelessIntegrationTests.java @@ -43,7 +43,6 @@ import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.web.client.RestClient; import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.APPLICATION_JSON; import static io.modelcontextprotocol.server.transport.HttpServletStatelessServerTransport.TEXT_EVENT_STREAM; @@ -122,12 +121,14 @@ void testToolCallSuccess(String clientType) { Tool.builder().name("tool1").title("tool1 description").inputSchema(EMPTY_JSON_SCHEMA).build(), (transportContext, request) -> { // perform a blocking call to a remote service - String response = RestClient.create() - .get() - .uri("https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md") - .retrieve() - .body(String.class); + String response = "{\"result\":\"test result\"}"; assertThat(response).isNotBlank(); + try { + Thread.sleep(1000L); + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } return callResponse; }); diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java index 270bc4308..ce1f4529d 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractMcpClientServerIntegrationTests.java @@ -4,10 +4,13 @@ package io.modelcontextprotocol; +import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; import java.util.List; import java.util.Map; @@ -49,6 +52,7 @@ import io.modelcontextprotocol.spec.McpSchema.Tool; import io.modelcontextprotocol.util.Utils; import net.javacrumbs.jsonunit.core.Option; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; @@ -62,18 +66,30 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertWith; import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public abstract class AbstractMcpClientServerIntegrationTests { protected ConcurrentHashMap clientBuilders = new ConcurrentHashMap<>(); + protected static HttpClient mockClient = mock(HttpClient.class); + abstract protected void prepareClients(int port, String mcpEndpoint); abstract protected McpServer.AsyncSpecification prepareAsyncServerBuilder(); abstract protected McpServer.SyncSpecification prepareSyncServerBuilder(); + @BeforeAll + protected static void initMockClient() throws IOException, InterruptedException { + HttpResponse mockResponse = mock(HttpResponse.class); + when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath())); + when(mockResponse.statusCode()).thenReturn(200); + when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse); + } + @ParameterizedTest(name = "{0} : {displayName} ") @MethodSource("clientsForTesting") void simple(String clientType) { @@ -778,12 +794,11 @@ void testToolCallSuccess(String clientType) { .callHandler((exchange, request) -> { try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); responseBodyIsNullOrBlank.set(!Utils.hasText(responseBody)); } @@ -927,12 +942,11 @@ void testToolListChangeHandlingSuccess(String clientType) { .callHandler((exchange, request) -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); } @@ -952,12 +966,11 @@ void testToolListChangeHandlingSuccess(String clientType) { try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); toolsRef.set(toolsUpdate); diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java index 240732ebe..c908741be 100644 --- a/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java +++ b/mcp-test/src/main/java/io/modelcontextprotocol/AbstractStatelessIntegrationTests.java @@ -4,10 +4,13 @@ package io.modelcontextprotocol; +import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Duration; import java.util.List; import java.util.Map; @@ -27,9 +30,9 @@ import io.modelcontextprotocol.spec.McpSchema.TextContent; import io.modelcontextprotocol.spec.McpSchema.Tool; import net.javacrumbs.jsonunit.core.Option; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; import reactor.core.publisher.Mono; import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA; @@ -38,17 +41,30 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.awaitility.Awaitility.await; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public abstract class AbstractStatelessIntegrationTests { protected ConcurrentHashMap clientBuilders = new ConcurrentHashMap<>(); + protected static HttpClient mockClient = mock(HttpClient.class); + abstract protected void prepareClients(int port, String mcpEndpoint); abstract protected StatelessAsyncSpecification prepareAsyncServerBuilder(); abstract protected StatelessSyncSpecification prepareSyncServerBuilder(); + @BeforeAll + protected static void initMockClient() throws IOException, InterruptedException { + HttpResponse mockResponse = mock(HttpResponse.class); + when(mockResponse.body()).thenReturn(Files.readString(Path.of("pom.xml").toAbsolutePath())); + when(mockResponse.statusCode()).thenReturn(200); + when(mockClient.send(any(HttpRequest.class), any(HttpResponse.BodyHandler.class))).thenReturn(mockResponse); + } + @ParameterizedTest(name = "{0} : {displayName} ") @MethodSource("clientsForTesting") void simple(String clientType) { @@ -89,12 +105,11 @@ void testToolCallSuccess(String clientType) { .callHandler((ctx, request) -> { try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); } @@ -177,12 +192,11 @@ void testToolListChangeHandlingSuccess(String clientType) { .callHandler((ctx, request) -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); } @@ -202,12 +216,11 @@ void testToolListChangeHandlingSuccess(String clientType) { try (var mcpClient = clientBuilder.toolsChangeConsumer(toolsUpdate -> { // perform a blocking call to a remote service try { - HttpResponse response = HttpClient.newHttpClient() - .send(HttpRequest.newBuilder() - .uri(URI.create( - "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) - .GET() - .build(), HttpResponse.BodyHandlers.ofString()); + HttpResponse response = mockClient.send(HttpRequest.newBuilder() + .uri(URI.create( + "https://raw.githubusercontent.com/modelcontextprotocol/java-sdk/refs/heads/main/README.md")) + .GET() + .build(), HttpResponse.BodyHandlers.ofString()); String responseBody = response.body(); assertThat(responseBody).isNotBlank(); }