Skip to content

Commit 4ff9e5e

Browse files
dreis2211wilkinsona
authored andcommitted
Split DeploymentIntegrationTests by container
Prior to this commit, every test started a new testcontainer. By splitting the tests apart we can make use of static containers that are only instantiated once per application (TomEE, Wildfly etc.) See gh-25446
1 parent d55d8d6 commit 4ff9e5e

File tree

6 files changed

+211
-65
lines changed

6 files changed

+211
-65
lines changed

spring-boot-tests/spring-boot-deployment-tests/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ dependencies {
2323
intTestImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
2424
intTestImplementation("org.apache.httpcomponents:httpasyncclient")
2525
intTestImplementation("org.awaitility:awaitility")
26+
intTestImplementation("org.testcontainers:junit-jupiter")
2627
intTestImplementation("org.testcontainers:testcontainers")
2728
intTestImplementation("org.springframework:spring-web")
2829

spring-boot-tests/spring-boot-deployment-tests/src/intTest/java/sample/AbstractDeploymentIntegrationTests.java

Lines changed: 47 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,21 +18,17 @@
1818

1919
import java.io.File;
2020
import java.time.Duration;
21-
import java.util.Arrays;
22-
import java.util.List;
2321
import java.util.function.Consumer;
2422

2523
import org.apache.http.impl.client.HttpClients;
2624
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
2725
import org.awaitility.Awaitility;
2826
import org.awaitility.core.ConditionTimeoutException;
29-
import org.junit.jupiter.params.ParameterizedTest;
30-
import org.junit.jupiter.params.provider.MethodSource;
27+
import org.junit.jupiter.api.Test;
3128
import org.testcontainers.containers.GenericContainer;
3229
import org.testcontainers.images.builder.ImageFromDockerfile;
3330

3431
import org.springframework.boot.test.web.client.TestRestTemplate;
35-
import org.springframework.boot.testsupport.testcontainers.DisabledIfDockerUnavailable;
3632
import org.springframework.boot.web.client.RestTemplateBuilder;
3733
import org.springframework.http.HttpStatus;
3834
import org.springframework.http.ResponseEntity;
@@ -41,102 +37,88 @@
4137
import static org.assertj.core.api.Assertions.assertThat;
4238

4339
/**
44-
* Deployment integration tests.
40+
* Abstract class for deployment integration tests.
4541
*/
46-
@DisabledIfDockerUnavailable
47-
class AbstractDeploymentIntegrationTests {
42+
abstract class AbstractDeploymentIntegrationTests {
4843

49-
@ParameterizedTest
50-
@MethodSource("deployedApplications")
51-
void home(DeployedApplication app) {
52-
app.test((rest) -> {
44+
protected static final int DEFAULT_PORT = 8080;
45+
46+
@Test
47+
void home() {
48+
getDeployedApplication().test((rest) -> {
5349
ResponseEntity<String> response = rest.getForEntity("/", String.class);
5450
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
5551
assertThat(response.getBody()).isEqualTo("Hello World");
5652
});
5753
}
5854

59-
@ParameterizedTest
60-
@MethodSource("deployedApplications")
61-
void health(DeployedApplication application) {
62-
application.test((rest) -> {
55+
@Test
56+
void health() {
57+
getDeployedApplication().test((rest) -> {
6358
ResponseEntity<String> response = rest.getForEntity("/actuator/health", String.class);
6459
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
6560
assertThat(response.getBody()).isEqualTo("{\"status\":\"UP\"}");
6661
});
6762
}
6863

69-
@ParameterizedTest
70-
@MethodSource("deployedApplications")
71-
void conditionalOnWarShouldBeTrue(DeployedApplication application) throws Exception {
72-
application.test((rest) -> {
64+
@Test
65+
void conditionalOnWarShouldBeTrue() {
66+
getDeployedApplication().test((rest) -> {
7367
ResponseEntity<String> response = rest.getForEntity("/actuator/war", String.class);
7468
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
7569
assertThat(response.getBody()).isEqualTo("{\"hello\":\"world\"}");
7670
});
7771
}
7872

79-
static List<DeployedApplication> deployedApplications() {
80-
return Arrays.asList(
81-
new DeployedApplication("openliberty/open-liberty:20.0.0.9-kernel-java8-openj9-ubi", "/config/dropins",
82-
9080),
83-
new DeployedApplication("tomcat:9.0.37-jdk8-openjdk", "/usr/local/tomcat/webapps", 8080),
84-
new DeployedApplication("tomee:8-jre-8.0.2-webprofile", "/usr/local/tomee/webapps", 8080),
85-
new DeployedApplication("jboss/wildfly:20.0.1.Final", "/opt/jboss/wildfly/standalone/deployments",
86-
8080));
73+
private DeployedApplication getDeployedApplication() {
74+
return new DeployedApplication(getContainer(), getPort());
75+
}
76+
77+
protected int getPort() {
78+
return DEFAULT_PORT;
8779
}
8880

89-
public static final class DeployedApplication {
81+
abstract WarDeploymentContainer getContainer();
9082

91-
private final String baseImage;
83+
static final class DeployedApplication {
9284

93-
private final String deploymentLocation;
85+
private final WarDeploymentContainer container;
9486

9587
private final int port;
9688

97-
private DeployedApplication(String baseImage, String deploymentLocation, int port) {
98-
this.baseImage = baseImage;
99-
this.deploymentLocation = deploymentLocation;
89+
DeployedApplication(WarDeploymentContainer container, int port) {
90+
this.container = container;
10091
this.port = port;
10192
}
10293

10394
private void test(Consumer<TestRestTemplate> consumer) {
104-
try (WarDeploymentContainer container = new WarDeploymentContainer(this.baseImage, this.deploymentLocation,
105-
this.port)) {
106-
container.start();
107-
TestRestTemplate rest = new TestRestTemplate(new RestTemplateBuilder()
108-
.rootUri("http://" + container.getHost() + ":" + container.getMappedPort(this.port)
109-
+ "/spring-boot")
110-
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory(HttpClients.custom()
111-
.setRetryHandler(new StandardHttpRequestRetryHandler(10, false)).build())));
112-
try {
113-
Awaitility.await().atMost(Duration.ofMinutes(10)).until(() -> {
114-
try {
115-
consumer.accept(rest);
116-
return true;
117-
}
118-
catch (Throwable ex) {
119-
return false;
120-
}
121-
});
122-
}
123-
catch (ConditionTimeoutException ex) {
124-
System.out.println(container.getLogs());
125-
throw ex;
126-
}
95+
TestRestTemplate rest = new TestRestTemplate(new RestTemplateBuilder()
96+
.rootUri("http://" + this.container.getHost() + ":" + this.container.getMappedPort(this.port)
97+
+ "/spring-boot")
98+
.requestFactory(() -> new HttpComponentsClientHttpRequestFactory(HttpClients.custom()
99+
.setRetryHandler(new StandardHttpRequestRetryHandler(10, false)).build())));
100+
try {
101+
Awaitility.await().atMost(Duration.ofMinutes(10)).until(() -> {
102+
try {
103+
consumer.accept(rest);
104+
return true;
105+
}
106+
catch (Throwable ex) {
107+
return false;
108+
}
109+
});
110+
}
111+
catch (ConditionTimeoutException ex) {
112+
System.out.println(this.container.getLogs());
113+
throw ex;
127114
}
128-
}
129-
130-
@Override
131-
public String toString() {
132-
return this.baseImage;
133115
}
134116

135117
}
136118

137-
private static final class WarDeploymentContainer extends GenericContainer<WarDeploymentContainer> {
119+
static final class WarDeploymentContainer extends GenericContainer<WarDeploymentContainer> {
138120

139-
private WarDeploymentContainer(String baseImage, String deploymentLocation, int port) {
121+
WarDeploymentContainer(String baseImage, String deploymentLocation, int port) {
140122
super(new ImageFromDockerfile().withFileFromFile("spring-boot.war", findWarToDeploy())
141123
.withDockerfileFromBuilder((builder) -> builder.from(baseImage)
142124
.add("spring-boot.war", deploymentLocation + "/spring-boot.war").build()));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample;
18+
19+
import org.testcontainers.junit.jupiter.Container;
20+
import org.testcontainers.junit.jupiter.Testcontainers;
21+
22+
/**
23+
* Deployment integration tests for Open Liberty.
24+
*
25+
* @author Christoph Dreis
26+
*/
27+
@Testcontainers(disabledWithoutDocker = true)
28+
class OpenLibertyDeploymentIntegrationTests extends AbstractDeploymentIntegrationTests {
29+
30+
private static final int PORT = 9080;
31+
32+
@Container
33+
static WarDeploymentContainer container = new WarDeploymentContainer(
34+
"openliberty/open-liberty:20.0.0.9-kernel-java8-openj9-ubi", "/config/dropins", PORT);
35+
36+
@Override
37+
WarDeploymentContainer getContainer() {
38+
return container;
39+
}
40+
41+
@Override
42+
protected int getPort() {
43+
return PORT;
44+
}
45+
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample;
18+
19+
import org.testcontainers.junit.jupiter.Container;
20+
import org.testcontainers.junit.jupiter.Testcontainers;
21+
22+
/**
23+
* Deployment integration tests for TomEE.
24+
*
25+
* @author Christoph Dreis
26+
*/
27+
@Testcontainers(disabledWithoutDocker = true)
28+
public class TomEEDeploymentIntegrationTests extends AbstractDeploymentIntegrationTests {
29+
30+
@Container
31+
static WarDeploymentContainer container = new WarDeploymentContainer("tomee:8-jre-8.0.2-webprofile",
32+
"/usr/local/tomee/webapps", DEFAULT_PORT);
33+
34+
@Override
35+
WarDeploymentContainer getContainer() {
36+
return container;
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample;
18+
19+
import org.testcontainers.junit.jupiter.Container;
20+
import org.testcontainers.junit.jupiter.Testcontainers;
21+
22+
/**
23+
* Deployment integration tests for Tomcat.
24+
*
25+
* @author Christoph Dreis
26+
*/
27+
@Testcontainers(disabledWithoutDocker = true)
28+
public class TomcatDeploymentIntegrationTests extends AbstractDeploymentIntegrationTests {
29+
30+
@Container
31+
static WarDeploymentContainer container = new WarDeploymentContainer("tomcat:9.0.37-jdk8-openjdk",
32+
"/usr/local/tomcat/webapps", DEFAULT_PORT);
33+
34+
@Override
35+
WarDeploymentContainer getContainer() {
36+
return container;
37+
}
38+
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2012-2021 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package sample;
18+
19+
import org.testcontainers.junit.jupiter.Container;
20+
import org.testcontainers.junit.jupiter.Testcontainers;
21+
22+
/**
23+
* Deployment integration tests for Wildfly.
24+
*
25+
* @author Christoph Dreis
26+
*/
27+
@Testcontainers(disabledWithoutDocker = true)
28+
public class WildflyDeploymentIntegrationTests extends AbstractDeploymentIntegrationTests {
29+
30+
@Container
31+
static WarDeploymentContainer container = new WarDeploymentContainer("jboss/wildfly:20.0.1.Final",
32+
"/opt/jboss/wildfly/standalone/deployments", DEFAULT_PORT);
33+
34+
@Override
35+
WarDeploymentContainer getContainer() {
36+
return container;
37+
}
38+
39+
}

0 commit comments

Comments
 (0)