Skip to content

Commit 77b85f7

Browse files
authored
IGNITE-27447 Replace mock-server with wiremock (#7298)
1 parent 41a5034 commit 77b85f7

File tree

14 files changed

+212
-438
lines changed

14 files changed

+212
-438
lines changed

gradle/libs.versions.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ caffeine = "3.2.0"
7373
fastutil = "8.5.18"
7474
kryo = "5.6.2"
7575
bytebuddy = "1.18.1"
76-
mockServer = "5.15.0"
76+
wiremock = "3.13.2"
7777
archunit = "1.4.1"
7878
testkit = "1.14.0"
7979
openapi = "4.10.0"
@@ -216,8 +216,7 @@ threetenbp = { module = "org.threeten:threetenbp", version.ref = "threetenbp" }
216216
swaggerv3-annotations = { module = "io.swagger.core.v3:swagger-annotations", version.ref = "swagger" }
217217
swagger-parser = { module = "io.swagger.parser.v3:swagger-parser", version.ref = "swaggerParser" }
218218

219-
mock-server-netty = { module = "org.mock-server:mockserver-netty", version.ref = "mockServer" }
220-
mock-server-junit = { module = "org.mock-server:mockserver-junit-jupiter", version.ref = "mockServer" }
219+
wiremock = { module = "org.wiremock:wiremock", version.ref = "wiremock" }
221220

222221
msgpack-core = { module = "org.msgpack:msgpack-core", version.ref = "msgpack" }
223222

modules/cli/build.gradle

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,7 @@ dependencies {
8484
testImplementation libs.micronaut.junit5
8585
testImplementation libs.micronaut.test
8686
testImplementation libs.assertj.core
87-
testImplementation libs.mock.server.netty
88-
testImplementation libs.mock.server.junit
87+
testImplementation libs.wiremock
8988
testImplementation libs.awaitility
9089

9190
testFixturesAnnotationProcessor libs.picocli.annotation.processor
@@ -113,8 +112,7 @@ dependencies {
113112
integrationTestImplementation testFixtures(project(':ignite-api'))
114113
integrationTestImplementation testFixtures(project(':ignite-runner'))
115114
integrationTestImplementation libs.micronaut.picocli
116-
integrationTestImplementation libs.mock.server.netty
117-
integrationTestImplementation libs.mock.server.junit
115+
integrationTestImplementation libs.wiremock
118116
integrationTestImplementation libs.micronaut.junit5
119117
integrationTestImplementation libs.micronaut.test
120118
integrationTestImplementation libs.assertj.core

modules/cli/src/test/java/org/apache/ignite/internal/cli/call/node/status/NodeStatusCallTest.java

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717

1818
package org.apache.ignite.internal.cli.call.node.status;
1919

20+
import static com.github.tomakehurst.wiremock.client.WireMock.get;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
2023
import static org.hamcrest.MatcherAssert.assertThat;
2124
import static org.hamcrest.Matchers.equalToIgnoringCase;
2225
import static org.hamcrest.Matchers.is;
23-
import static org.mockserver.model.HttpRequest.request;
24-
import static org.mockserver.model.HttpResponse.response;
2526

2627
import com.fasterxml.jackson.core.JsonProcessingException;
2728
import com.fasterxml.jackson.databind.ObjectMapper;
29+
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
30+
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
2831
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
2932
import jakarta.inject.Inject;
3033
import java.util.Arrays;
@@ -37,13 +40,11 @@
3740
import org.junit.jupiter.params.ParameterizedTest;
3841
import org.junit.jupiter.params.provider.Arguments;
3942
import org.junit.jupiter.params.provider.MethodSource;
40-
import org.mockserver.integration.ClientAndServer;
4143

4244
@MicronautTest(rebuildContext = true)
45+
@WireMockTest
4346
class NodeStatusCallTest {
4447

45-
private ClientAndServer clientAndServer;
46-
4748
private ObjectMapper objectMapper;
4849

4950
private String url;
@@ -58,12 +59,11 @@ private static Stream<Arguments> nodeStates() {
5859
}
5960

6061
@BeforeEach
61-
void setUp() {
62+
void setUp(WireMockRuntimeInfo wmRuntimeInfo) {
6263
nodeName = "testnode";
6364
objectMapper = new ObjectMapper();
6465

65-
clientAndServer = ClientAndServer.startClientAndServer(0);
66-
url = "http://localhost:" + clientAndServer.getPort();
66+
url = wmRuntimeInfo.getHttpBaseUrl();
6767
}
6868

6969
@ParameterizedTest
@@ -85,11 +85,8 @@ void nodeStatusStarting(org.apache.ignite.rest.client.model.State givenNodeState
8585

8686
private void nodeState(org.apache.ignite.rest.client.model.State state) {
8787
try {
88-
clientAndServer
89-
.when(request()
90-
.withMethod("GET")
91-
.withPath("/management/v1/node/state"))
92-
.respond(response(objectMapper.writeValueAsString(new NodeState().name(nodeName).state(state))));
88+
stubFor(get("/management/v1/node/state")
89+
.willReturn(ok(objectMapper.writeValueAsString(new NodeState().name(nodeName).state(state)))));
9390
} catch (JsonProcessingException e) {
9491
throw new RuntimeException(e);
9592
}

modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/IgniteCliInterfaceTestBase.java

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,46 @@
1717

1818
package org.apache.ignite.internal.cli.commands;
1919

20+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
23+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
24+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
25+
import static org.apache.ignite.internal.rest.constants.MediaType.APPLICATION_JSON_UTF8;
26+
27+
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
28+
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
2029
import org.junit.jupiter.api.BeforeAll;
21-
import org.junit.jupiter.api.BeforeEach;
22-
import org.junit.jupiter.api.extension.ExtendWith;
23-
import org.mockserver.integration.ClientAndServer;
24-
import org.mockserver.junit.jupiter.MockServerExtension;
2530

2631
/**
2732
* Base class for testing CLI interface.
2833
*/
29-
@ExtendWith(MockServerExtension.class)
34+
@WireMockTest
3035
public class IgniteCliInterfaceTestBase extends CliCommandTestBase {
31-
protected static ClientAndServer clientAndServer;
32-
3336
protected static String mockUrl;
3437

38+
protected static void returnOkForPostWithJson(String partitionsRestartEndpoint, String expectedSentContent) {
39+
returnOkForPostWithJson(partitionsRestartEndpoint, expectedSentContent, false);
40+
}
41+
42+
protected static void returnOkForPostWithJson(
43+
String partitionsRestartEndpoint,
44+
String expectedSentContent,
45+
boolean ignoreExtraElements
46+
) {
47+
stubFor(post(partitionsRestartEndpoint)
48+
.withRequestBody(equalToJson(expectedSentContent, false, ignoreExtraElements))
49+
.withHeader("Content-Type", equalTo(APPLICATION_JSON_UTF8))
50+
.willReturn(ok()));
51+
}
52+
3553
@Override
3654
protected Class<?> getCommandClass() {
3755
return TopLevelCliCommand.class;
3856
}
3957

4058
@BeforeAll
41-
static void initMockServer(ClientAndServer clientAndServer) {
42-
IgniteCliInterfaceTestBase.clientAndServer = clientAndServer;
43-
mockUrl = "http://localhost:" + clientAndServer.getPort();
44-
}
45-
46-
@BeforeEach
47-
void resetMockServer() {
48-
clientAndServer.reset();
59+
static void initMockServer(WireMockRuntimeInfo wmRuntimeInfo) {
60+
mockUrl = wmRuntimeInfo.getHttpBaseUrl();
4961
}
5062
}

modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/cluster/ClusterInitTest.java

Lines changed: 39 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@
1717

1818
package org.apache.ignite.internal.cli.commands.cluster;
1919

20+
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.serverError;
23+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
2024
import static org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerHelper.copyResourceToTempFile;
2125
import static org.junit.jupiter.api.Assertions.assertAll;
22-
import static org.mockserver.matchers.MatchType.ONLY_MATCHING_FIELDS;
23-
import static org.mockserver.model.HttpRequest.request;
24-
import static org.mockserver.model.HttpResponse.response;
25-
import static org.mockserver.model.HttpStatusCode.INTERNAL_SERVER_ERROR_500;
26-
import static org.mockserver.model.JsonBody.json;
2726

2827
import com.typesafe.config.ConfigFactory;
2928
import com.typesafe.config.ConfigRenderOptions;
@@ -39,13 +38,13 @@
3938
import org.junit.jupiter.api.DisplayName;
4039
import org.junit.jupiter.api.Test;
4140
import org.junit.jupiter.api.extension.ExtendWith;
42-
import org.mockserver.model.MediaType;
4341

4442
/** Tests "cluster init" command. */
4543
@DisplayName("cluster init")
4644
@ExtendWith(WorkDirectoryExtension.class)
4745
class ClusterInitTest extends IgniteCliInterfaceTestBase {
48-
private static final Pattern PATTERN = Pattern.compile("\"");
46+
private static final Pattern QUOTE_PATTERN = Pattern.compile("\"");
47+
private static final Pattern CR_PATTERN = Pattern.compile("\n");
4948

5049
@Override
5150
protected Class<?> getCommandClass() {
@@ -68,7 +67,8 @@ void duplicatedOption() {
6867

6968
@Test
7069
void wrongConfigFilePath() {
71-
clientAndServer.when(request().withMethod("POST").withPath("/management/v1/cluster/init")).respond(response(null));
70+
stubFor(post("/management/v1/cluster/init")
71+
.willReturn(ok()));
7272

7373
execute(
7474
"--url", mockUrl,
@@ -115,14 +115,7 @@ void initSuccess() {
115115
+ "\"cmgNodes\":[\"node2ConsistentId\",\"node3ConsistentId\"],"
116116
+ "\"clusterName\":\"cluster\"}";
117117

118-
clientAndServer
119-
.when(request()
120-
.withMethod("POST")
121-
.withPath("/management/v1/cluster/init")
122-
.withBody(json(expectedSentContent, ONLY_MATCHING_FIELDS))
123-
.withContentType(MediaType.APPLICATION_JSON_UTF_8)
124-
)
125-
.respond(response(null));
118+
returnOkForPostWithJson("/management/v1/cluster/init", expectedSentContent, true);
126119

127120
execute(
128121
"--url", mockUrl,
@@ -141,14 +134,7 @@ void initSuccessNoMsCmg() {
141134
+ "\"cmgNodes\":[],"
142135
+ "\"clusterName\":\"cluster\"}";
143136

144-
clientAndServer
145-
.when(request()
146-
.withMethod("POST")
147-
.withPath("/management/v1/cluster/init")
148-
.withBody(json(expectedSentContent, ONLY_MATCHING_FIELDS))
149-
.withContentType(MediaType.APPLICATION_JSON_UTF_8)
150-
)
151-
.respond(response(null));
137+
returnOkForPostWithJson("/management/v1/cluster/init", expectedSentContent, true);
152138

153139
execute(
154140
"--url", mockUrl,
@@ -167,27 +153,20 @@ void initWithAuthenticationSuccess() throws IOException {
167153
Path clusterConfigurationFile = copyResourceToTempFile("cluster-configuration-with-enabled-auth.conf").toPath();
168154
String clusterConfiguration = Files.readString(clusterConfigurationFile);
169155

170-
String expectedSentContent = "{\n"
171-
+ " \"metaStorageNodes\": [\n"
172-
+ " \"node1ConsistentId\",\n"
173-
+ " \"node2ConsistentId\"\n"
174-
+ " ],\n"
175-
+ " \"cmgNodes\": [\n"
176-
+ " \"node2ConsistentId\",\n"
177-
+ " \"node3ConsistentId\"\n"
178-
+ " ],\n"
179-
+ " \"clusterName\": \"cluster\",\n"
180-
+ " \"clusterConfiguration\": \"" + escapedJson(clusterConfiguration) + "\"\n"
156+
String expectedSentContent = "{"
157+
+ " \"metaStorageNodes\": ["
158+
+ " \"node1ConsistentId\","
159+
+ " \"node2ConsistentId\""
160+
+ " ],"
161+
+ " \"cmgNodes\": ["
162+
+ " \"node2ConsistentId\","
163+
+ " \"node3ConsistentId\""
164+
+ " ],"
165+
+ " \"clusterName\": \"cluster\","
166+
+ " \"clusterConfiguration\": \"" + escapedJson(clusterConfiguration) + "\""
181167
+ "}";
182168

183-
clientAndServer
184-
.when(request()
185-
.withMethod("POST")
186-
.withPath("/management/v1/cluster/init")
187-
.withBody(json(expectedSentContent, ONLY_MATCHING_FIELDS))
188-
.withContentType(MediaType.APPLICATION_JSON_UTF_8)
189-
)
190-
.respond(response(null));
169+
returnOkForPostWithJson("/management/v1/cluster/init", expectedSentContent, true);
191170

192171
execute(
193172
"--url", mockUrl,
@@ -202,15 +181,8 @@ void initWithAuthenticationSuccess() throws IOException {
202181

203182
@Test
204183
void initError() {
205-
clientAndServer
206-
.when(request()
207-
.withMethod("POST")
208-
.withPath("/management/v1/cluster/init")
209-
)
210-
.respond(response()
211-
.withStatusCode(INTERNAL_SERVER_ERROR_500.code())
212-
.withBody("{\"status\":500, \"detail\":\"Oops\"}")
213-
);
184+
stubFor(post("/management/v1/cluster/init")
185+
.willReturn(serverError().withBody("{\"status\":500, \"detail\":\"Oops\"}")));
214186

215187
execute(
216188
"--url", mockUrl,
@@ -234,14 +206,7 @@ void metastorageNodesAreNotMandatoryForInit() {
234206
+ "\"cmgNodes\":[\"node2ConsistentId\",\"node3ConsistentId\"],"
235207
+ "\"clusterName\":\"cluster\"}";
236208

237-
clientAndServer
238-
.when(request()
239-
.withMethod("POST")
240-
.withPath("/management/v1/cluster/init")
241-
.withBody(json(expectedSentContent, ONLY_MATCHING_FIELDS))
242-
.withContentType(MediaType.APPLICATION_JSON_UTF_8)
243-
)
244-
.respond(response(null));
209+
returnOkForPostWithJson("/management/v1/cluster/init", expectedSentContent, true);
245210

246211
execute(
247212
"--url", mockUrl,
@@ -255,7 +220,7 @@ void metastorageNodesAreNotMandatoryForInit() {
255220
@Test
256221
@DisplayName("--url http://localhost:10300 --metastorage-group node2ConsistentId, node3ConsistentId")
257222
void cmgNodesAreNotMandatoryForInit() {
258-
clientAndServer.when(request().withMethod("POST").withPath("/management/v1/cluster/init")).respond(response(null));
223+
stubFor(post("/management/v1/cluster/init").willReturn(ok()));
259224

260225
execute(
261226
"--url", mockUrl,
@@ -310,25 +275,18 @@ void clusterInitFromMultipleConfigFiles() {
310275
+ "ignite.system.idleSafeTimeSyncIntervalMillis: 10,\n"
311276
+ "ignite.replication.idleSafeTimePropagationDurationMillis: 100";
312277

313-
String expectedSentContent = "{\n"
314-
+ " \"metaStorageNodes\": [\n"
315-
+ " \"node1ConsistentId\"\n"
316-
+ " ],\n"
317-
+ " \"cmgNodes\": [\n"
318-
+ " \"node2ConsistentId\"\n"
319-
+ " ],\n"
320-
+ " \"clusterName\": \"cluster\",\n"
321-
+ " \"clusterConfiguration\": \"" + escapedJson(expectedClusterConfiguration) + "\"\n"
278+
String expectedSentContent = "{"
279+
+ " \"metaStorageNodes\": ["
280+
+ " \"node1ConsistentId\""
281+
+ " ],"
282+
+ " \"cmgNodes\": ["
283+
+ " \"node2ConsistentId\""
284+
+ " ],"
285+
+ " \"clusterName\": \"cluster\","
286+
+ " \"clusterConfiguration\": \"" + escapedJson(expectedClusterConfiguration) + "\""
322287
+ "}";
323288

324-
clientAndServer
325-
.when(request()
326-
.withMethod("POST")
327-
.withPath("/management/v1/cluster/init")
328-
.withBody(json(expectedSentContent, ONLY_MATCHING_FIELDS))
329-
.withContentType(MediaType.APPLICATION_JSON_UTF_8)
330-
)
331-
.respond(response(null));
289+
returnOkForPostWithJson("/management/v1/cluster/init", expectedSentContent, true);
332290

333291
execute(
334292
"--url", mockUrl,
@@ -345,6 +303,8 @@ private static String escapedJson(String configuration) {
345303
String json = ConfigFactory.parseString(configuration)
346304
.root().render(ConfigRenderOptions.concise().setFormatted(true).setJson(true));
347305

348-
return PATTERN.matcher(json).replaceAll("\\\\\"");
306+
String quoted = QUOTE_PATTERN.matcher(json).replaceAll("\\\\\"");
307+
308+
return CR_PATTERN.matcher(quoted).replaceAll("\\\\n");
349309
}
350310
}

0 commit comments

Comments
 (0)