Skip to content

Commit b6dff0d

Browse files
committed
Add LauncherSessionListener example to user guide
1 parent 439084d commit b6dff0d

File tree

4 files changed

+161
-4
lines changed

4 files changed

+161
-4
lines changed

documentation/src/docs/asciidoc/user-guide/launcher-api.adoc

+42-4
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,48 @@ programmatically via the `{LauncherConfig}` that is passed to the `{LauncherFact
130130
they can be discovered at runtime via Java's `{ServiceLoader}` mechanism and automatically
131131
registered with `LauncherSession` (unless automatic registration is disabled.)
132132

133-
For example, an `example.CustomLauncherSessionListener` class implementing
134-
`LauncherSessionListener` and declared within the
135-
`/META-INF/services/org.junit.platform.launcher.LauncherSessionListener` file is loaded
136-
and registered automatically.
133+
A `{LauncherSessionListener}` is well suited for implementing once-per-JVM setup/teardown
134+
behavior since it's called before the first and after the last test in a launcher session,
135+
respectively. The scope of a launcher session depends on the used IDE or build tool but
136+
usually corresponds to the lifecycle of the test JVM. A custom listener that starts an
137+
HTTP server before executing the first test and stops it after the last test has been
138+
executed, could look like this:
139+
140+
[source,java]
141+
.src/test/java/example/session/GlobalSetupTeardownListener.java
142+
----
143+
package example.session;
144+
145+
include::{testDir}/example/session/GlobalSetupTeardownListener.java[tags=user_guide]
146+
----
147+
<1> Start the HTTP server
148+
<2> Export its dynamic port as a system property for consumption by tests
149+
<3> Stop the HTTP server
150+
151+
This sample uses the HTTP server implementation from the jdk.httpserver module that comes
152+
with the JDK but would work similarly with any other server or resource. In order for the
153+
listener to be picked up by JUnit Platform, you need to register it as a service by adding
154+
a resource file with the following name and contents to your test runtime classpath (e.g.
155+
by adding the file to `src/test/resources`):
156+
157+
[source]
158+
.src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener
159+
----
160+
include::{testResourcesDir}/META-INF/services/org.junit.platform.launcher.LauncherSessionListener[]
161+
----
162+
163+
You can now use the resource from your test:
164+
165+
[source,java]
166+
.src/test/java/example/session/HttpTests.java
167+
----
168+
package example.session;
169+
170+
include::{testDir}/example/session/HttpTests.java[tags=user_guide]
171+
----
172+
<1> Read the port of the server from the system property set by the listener
173+
<2> Send a request to the server
174+
<3> Check the status code of the response
137175

138176
[[launcher-api-launcher-discovery-listeners-custom]]
139177
==== Registering a LauncherDiscoveryListener
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2015-2021 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package example.session;
12+
13+
//tag::user_guide[]
14+
import java.io.IOException;
15+
import java.io.UncheckedIOException;
16+
import java.net.InetSocketAddress;
17+
import java.util.concurrent.ExecutorService;
18+
import java.util.concurrent.Executors;
19+
20+
import com.sun.net.httpserver.HttpServer;
21+
22+
import org.junit.platform.launcher.LauncherSession;
23+
import org.junit.platform.launcher.LauncherSessionListener;
24+
import org.junit.platform.launcher.TestExecutionListener;
25+
import org.junit.platform.launcher.TestPlan;
26+
27+
public class GlobalSetupTeardownListener implements LauncherSessionListener {
28+
29+
private Fixture fixture;
30+
31+
@Override
32+
public void launcherSessionOpened(LauncherSession session) {
33+
// Avoid setup for test discovery by delaying it until tests are about to be executed
34+
session.getLauncher().registerTestExecutionListeners(new TestExecutionListener() {
35+
@Override
36+
public void testPlanExecutionStarted(TestPlan testPlan) {
37+
if (fixture == null) {
38+
fixture = new Fixture();
39+
fixture.setUp();
40+
}
41+
}
42+
});
43+
}
44+
45+
@Override
46+
public void launcherSessionClosed(LauncherSession session) {
47+
if (fixture != null) {
48+
fixture.tearDown();
49+
fixture = null;
50+
}
51+
}
52+
53+
static class Fixture {
54+
55+
private HttpServer server;
56+
private ExecutorService executorService;
57+
58+
void setUp() {
59+
try {
60+
server = HttpServer.create(new InetSocketAddress(0), 0);
61+
}
62+
catch (IOException e) {
63+
throw new UncheckedIOException("Failed to start HTTP server", e);
64+
}
65+
server.createContext("/test", exchange -> {
66+
exchange.sendResponseHeaders(204, -1);
67+
exchange.close();
68+
});
69+
executorService = Executors.newCachedThreadPool();
70+
server.setExecutor(executorService);
71+
server.start(); // <1>
72+
int port = server.getAddress().getPort();
73+
System.setProperty("http.server.port", String.valueOf(port)); // <2>
74+
}
75+
76+
void tearDown() {
77+
server.stop(0); // <3>
78+
executorService.shutdownNow();
79+
}
80+
}
81+
82+
}
83+
//end::user_guide[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2015-2021 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
11+
package example.session;
12+
13+
//tag::user_guide[]
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
16+
import java.net.HttpURLConnection;
17+
import java.net.URL;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
class HttpTests {
22+
23+
@Test
24+
void respondsWith204() throws Exception {
25+
String port = System.getProperty("http.server.port"); // <1>
26+
URL url = new URL("http://localhost:" + port + "/test");
27+
28+
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
29+
connection.setRequestMethod("GET");
30+
int responseCode = connection.getResponseCode(); // <2>
31+
32+
assertEquals(204, responseCode); // <3>
33+
}
34+
}
35+
//end::user_guide[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example.session.GlobalSetupTeardownListener

0 commit comments

Comments
 (0)