Skip to content

Commit 14948cb

Browse files
committed
Merge pull request #25457 from dreis2211
* gh-25457: Speed up spring-boot-server-tests Closes gh-25457
2 parents dd2dc22 + b0a6e92 commit 14948cb

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/test/java/org/springframework/boot/context/embedded/AbstractApplicationLauncher.java

Lines changed: 9 additions & 9 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.
@@ -26,7 +26,6 @@
2626
import java.util.List;
2727

2828
import org.awaitility.Awaitility;
29-
import org.junit.jupiter.api.extension.AfterEachCallback;
3029
import org.junit.jupiter.api.extension.BeforeEachCallback;
3130
import org.junit.jupiter.api.extension.ExtensionContext;
3231

@@ -40,7 +39,7 @@
4039
*
4140
* @author Andy Wilkinson
4241
*/
43-
abstract class AbstractApplicationLauncher implements BeforeEachCallback, AfterEachCallback {
42+
abstract class AbstractApplicationLauncher implements BeforeEachCallback {
4443

4544
private final ApplicationBuilder applicationBuilder;
4645

@@ -56,15 +55,16 @@ protected AbstractApplicationLauncher(ApplicationBuilder applicationBuilder, Bui
5655
}
5756

5857
@Override
59-
public void afterEach(ExtensionContext context) throws Exception {
60-
if (this.process != null) {
61-
this.process.destroy();
58+
public void beforeEach(ExtensionContext context) throws Exception {
59+
if (this.process == null) {
60+
this.process = startApplication();
6261
}
6362
}
6463

65-
@Override
66-
public void beforeEach(ExtensionContext context) throws Exception {
67-
this.process = startApplication();
64+
void destroyProcess() {
65+
if (this.process != null) {
66+
this.process.destroy();
67+
}
6868
}
6969

7070
final int getHttpPort() {

spring-boot-tests/spring-boot-integration-tests/spring-boot-server-tests/src/test/java/org/springframework/boot/context/embedded/EmbeddedServerContainerInvocationContextProvider.java

Lines changed: 38 additions & 6 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.
@@ -21,6 +21,7 @@
2121
import java.nio.file.Files;
2222
import java.nio.file.Path;
2323
import java.util.Arrays;
24+
import java.util.HashMap;
2425
import java.util.HashSet;
2526
import java.util.List;
2627
import java.util.Map;
@@ -62,6 +63,10 @@ class EmbeddedServerContainerInvocationContextProvider
6263
private static final BuildOutput buildOutput = new BuildOutput(
6364
EmbeddedServerContainerInvocationContextProvider.class);
6465

66+
private final Map<String, ApplicationBuilder> builderCache = new HashMap<>();
67+
68+
private final Map<String, AbstractApplicationLauncher> launcherCache = new HashMap<>();
69+
6570
private final Path tempDir;
6671

6772
EmbeddedServerContainerInvocationContextProvider() throws IOException {
@@ -77,14 +82,13 @@ public boolean supportsTestTemplate(ExtensionContext context) {
7782
public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContexts(ExtensionContext context) {
7883
EmbeddedServletContainerTest annotation = context.getRequiredTestClass()
7984
.getAnnotation(EmbeddedServletContainerTest.class);
80-
return CONTAINERS.stream()
81-
.map((container) -> new ApplicationBuilder(this.tempDir, annotation.packaging(),
82-
container))
85+
return CONTAINERS
86+
.stream().map(
87+
(container) -> getApplicationBuilder(annotation, container))
8388
.flatMap(
8489
(builder) -> Stream
8590
.of(annotation.launchers()).map(
86-
(launcherClass) -> ReflectionUtils.newInstance(launcherClass, builder,
87-
buildOutput))
91+
(launcherClass) -> getAbstractApplicationLauncher(builder, launcherClass))
8892
.map((launcher) -> new EmbeddedServletContainerInvocationContext(
8993
StringUtils.capitalize(builder.getContainer()) + ": "
9094
+ launcher.getDescription(builder.getPackaging()),
@@ -94,6 +98,34 @@ public Stream<TestTemplateInvocationContext> provideTestTemplateInvocationContex
9498
@Override
9599
public void afterAll(ExtensionContext context) throws Exception {
96100
FileSystemUtils.deleteRecursively(this.tempDir);
101+
cleanupCaches();
102+
}
103+
104+
private void cleanupCaches() {
105+
this.launcherCache.values().forEach(AbstractApplicationLauncher::destroyProcess);
106+
this.launcherCache.clear();
107+
this.builderCache.clear();
108+
}
109+
110+
private AbstractApplicationLauncher getAbstractApplicationLauncher(ApplicationBuilder builder,
111+
Class<? extends AbstractApplicationLauncher> launcherClass) {
112+
String cacheKey = builder.getContainer() + ":" + builder.getPackaging() + ":" + launcherClass.getName();
113+
if (this.launcherCache.containsKey(cacheKey)) {
114+
return this.launcherCache.get(cacheKey);
115+
}
116+
AbstractApplicationLauncher launcher = ReflectionUtils.newInstance(launcherClass, builder, buildOutput);
117+
this.launcherCache.put(cacheKey, launcher);
118+
return launcher;
119+
}
120+
121+
private ApplicationBuilder getApplicationBuilder(EmbeddedServletContainerTest annotation, String container) {
122+
String cacheKey = container + ":" + annotation.packaging();
123+
if (this.builderCache.containsKey(cacheKey)) {
124+
return this.builderCache.get(cacheKey);
125+
}
126+
ApplicationBuilder builder = new ApplicationBuilder(this.tempDir, annotation.packaging(), container);
127+
this.builderCache.put(cacheKey, builder);
128+
return builder;
97129
}
98130

99131
static class EmbeddedServletContainerInvocationContext implements TestTemplateInvocationContext, ParameterResolver {

0 commit comments

Comments
 (0)