refactor: standardize test parameterization and fix package naming (#556)

- Replace @ValueSource with @MethodSource for parameterized tests
- Add clientsForTesting() methods to provide test arguments consistently
- Remove hardcoded Spring-related labels from framework-agnostic mcp-test module
- Move mcp-test's utility classes from io.modelcontextprotocol.utils to io.modelcontextprotocol.util

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
This commit is contained in:
Christian Tzolov 2025-09-17 12:26:55 +02:00 • committed by GitHub
commit 8ac7eae47c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 134 additions and 76 deletions

View file

@ -50,11 +50,12 @@ import io.modelcontextprotocol.spec.McpSchema.Tool;
import io.modelcontextprotocol.util.Utils;
import net.javacrumbs.jsonunit.core.Option;
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 reactor.test.StepVerifier;
import static io.modelcontextprotocol.utils.ToolsUtils.EMPTY_JSON_SCHEMA;
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;
import static org.assertj.core.api.Assertions.assertThat;
@ -74,7 +75,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
abstract protected McpServer.SyncSpecification<?> prepareSyncServerBuilder();
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void simple(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -100,7 +101,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Sampling Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateMessageWithoutSamplingCapabilities(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -136,7 +137,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateMessageSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -205,7 +206,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateMessageWithRequestTimeoutSuccess(String clientType) throws InterruptedException {
// Client
@ -285,7 +286,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateMessageWithRequestTimeoutFail(String clientType) throws InterruptedException {
var clientBuilder = clientBuilders.get(clientType);
@ -351,7 +352,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Elicitation Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateElicitationWithoutElicitationCapabilities(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -383,7 +384,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateElicitationSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -440,7 +441,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateElicitationWithRequestTimeoutSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -501,7 +502,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCreateElicitationWithRequestTimeoutFail(String clientType) {
var latch = new CountDownLatch(1);
@ -572,7 +573,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Roots Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testRootsSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -620,7 +621,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testRootsWithoutCapability(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -659,7 +660,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testRootsNotificationWithEmptyRootsList(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -689,7 +690,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testRootsWithMultipleHandlers(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -723,7 +724,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testRootsServerCloseWithActiveSubscription(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -758,7 +759,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Tools Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testToolCallSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -809,7 +810,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -847,7 +848,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testToolCallSuccessWithTranportContextExtraction(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -904,7 +905,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testToolListChangeHandlingSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -997,7 +998,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testInitialize(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -1018,7 +1019,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Logging Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testLoggingNotification(String clientType) throws InterruptedException {
int expectedNotificationsCount = 3;
CountDownLatch latch = new CountDownLatch(expectedNotificationsCount);
@ -1131,7 +1132,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Progress Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testProgressNotification(String clientType) throws InterruptedException {
int expectedNotificationsCount = 4; // 3 notifications + 1 for another progress
// token
@ -1237,7 +1238,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Completion Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : Completion call")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testCompletionShouldReturnExpectedSuggestions(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -1288,7 +1289,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Ping Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testPingSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -1351,7 +1352,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
// Tool Structured Output Schema Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputValidationSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -1596,7 +1597,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputMissingStructuredContent(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -1647,7 +1648,7 @@ public abstract class AbstractMcpClientServerIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputRuntimeToolAddition(String clientType) {
var clientBuilder = clientBuilders.get(clientType);

View file

@ -28,10 +28,11 @@ import io.modelcontextprotocol.spec.McpSchema.TextContent;
import io.modelcontextprotocol.spec.McpSchema.Tool;
import net.javacrumbs.jsonunit.core.Option;
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.utils.ToolsUtils.EMPTY_JSON_SCHEMA;
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.json;
import static org.assertj.core.api.Assertions.assertThat;
@ -49,7 +50,7 @@ public abstract class AbstractStatelessIntegrationTests {
abstract protected StatelessSyncSpecification prepareSyncServerBuilder();
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void simple(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -76,7 +77,7 @@ public abstract class AbstractStatelessIntegrationTests {
// Tools Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testToolCallSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -126,7 +127,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testThrowingToolCallIsCaughtBeforeTimeout(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -164,7 +165,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testToolListChangeHandlingSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -246,7 +247,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testInitialize(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -267,7 +268,7 @@ public abstract class AbstractStatelessIntegrationTests {
// Tool Structured Output Schema Tests
// ---------------------------------------
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputValidationSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -342,7 +343,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputOfObjectArrayValidationSuccess(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -402,7 +403,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputWithInHandlerError(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -460,7 +461,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputValidationFailure(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -516,7 +517,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputMissingStructuredContent(String clientType) {
var clientBuilder = clientBuilders.get(clientType);
@ -567,7 +568,7 @@ public abstract class AbstractStatelessIntegrationTests {
}
@ParameterizedTest(name = "{0} : {displayName} ")
@ValueSource(strings = { "httpclient", "webflux" })
@MethodSource("clientsForTesting")
void testStructuredOutputRuntimeToolAddition(String clientType) {
var clientBuilder = clientBuilders.get(clientType);

View file

@ -4,7 +4,6 @@
package io.modelcontextprotocol.client;
import static io.modelcontextprotocol.utils.McpJsonMapperUtils.JSON_MAPPER;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -23,7 +22,6 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import io.modelcontextprotocol.json.McpJsonMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@ -54,6 +52,8 @@ import reactor.core.publisher.Mono;
import reactor.core.publisher.Sinks;
import reactor.test.StepVerifier;
import static io.modelcontextprotocol.util.McpJsonMapperUtils.JSON_MAPPER;
/**
* Test suite for the {@link McpAsyncClient} that can be used with different
* {@link McpTransport} implementations.

View file

@ -26,7 +26,7 @@ import org.junit.jupiter.params.provider.ValueSource;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import static io.modelcontextprotocol.utils.ToolsUtils.EMPTY_JSON_SCHEMA;
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

View file

@ -4,7 +4,6 @@
package io.modelcontextprotocol.server;
import static io.modelcontextprotocol.utils.ToolsUtils.EMPTY_JSON_SCHEMA;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@ -15,6 +14,8 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static io.modelcontextprotocol.util.ToolsUtils.EMPTY_JSON_SCHEMA;
import io.modelcontextprotocol.spec.McpError;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;

View file

@ -0,0 +1,12 @@
package io.modelcontextprotocol.util;
import io.modelcontextprotocol.json.McpJsonMapper;
public final class McpJsonMapperUtils {
private McpJsonMapperUtils() {
}
public static final McpJsonMapper JSON_MAPPER = McpJsonMapper.getDefault();
}

View file

@ -0,0 +1,15 @@
package io.modelcontextprotocol.util;
import io.modelcontextprotocol.spec.McpSchema;
import java.util.Collections;
public final class ToolsUtils {
private ToolsUtils() {
}
public static final McpSchema.JsonSchema EMPTY_JSON_SCHEMA = new McpSchema.JsonSchema("object",
Collections.emptyMap(), null, null, null, null);
}