Skip to content

Commit

Permalink
Add LauncherSessionListener example to user guide
Browse files Browse the repository at this point in the history
  • Loading branch information
marcphilipp committed Sep 12, 2021
1 parent 439084d commit b6dff0d
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 4 deletions.
46 changes: 42 additions & 4 deletions documentation/src/docs/asciidoc/user-guide/launcher-api.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,48 @@ programmatically via the `{LauncherConfig}` that is passed to the `{LauncherFact
they can be discovered at runtime via Java's `{ServiceLoader}` mechanism and automatically
registered with `LauncherSession` (unless automatic registration is disabled.)

For example, an `example.CustomLauncherSessionListener` class implementing
`LauncherSessionListener` and declared within the
`/META-INF/services/org.junit.platform.launcher.LauncherSessionListener` file is loaded
and registered automatically.
A `{LauncherSessionListener}` is well suited for implementing once-per-JVM setup/teardown
behavior since it's called before the first and after the last test in a launcher session,
respectively. The scope of a launcher session depends on the used IDE or build tool but
usually corresponds to the lifecycle of the test JVM. A custom listener that starts an
HTTP server before executing the first test and stops it after the last test has been
executed, could look like this:

[source,java]
.src/test/java/example/session/GlobalSetupTeardownListener.java
----
package example.session;
include::{testDir}/example/session/GlobalSetupTeardownListener.java[tags=user_guide]
----
<1> Start the HTTP server
<2> Export its dynamic port as a system property for consumption by tests
<3> Stop the HTTP server

This sample uses the HTTP server implementation from the jdk.httpserver module that comes
with the JDK but would work similarly with any other server or resource. In order for the
listener to be picked up by JUnit Platform, you need to register it as a service by adding
a resource file with the following name and contents to your test runtime classpath (e.g.
by adding the file to `src/test/resources`):

[source]
.src/test/resources/META-INF/services/org.junit.platform.launcher.LauncherSessionListener
----
include::{testResourcesDir}/META-INF/services/org.junit.platform.launcher.LauncherSessionListener[]
----

You can now use the resource from your test:

[source,java]
.src/test/java/example/session/HttpTests.java
----
package example.session;
include::{testDir}/example/session/HttpTests.java[tags=user_guide]
----
<1> Read the port of the server from the system property set by the listener
<2> Send a request to the server
<3> Check the status code of the response

[[launcher-api-launcher-discovery-listeners-custom]]
==== Registering a LauncherDiscoveryListener
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2015-2021 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package example.session;

//tag::user_guide[]
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.sun.net.httpserver.HttpServer;

import org.junit.platform.launcher.LauncherSession;
import org.junit.platform.launcher.LauncherSessionListener;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestPlan;

public class GlobalSetupTeardownListener implements LauncherSessionListener {

private Fixture fixture;

@Override
public void launcherSessionOpened(LauncherSession session) {
// Avoid setup for test discovery by delaying it until tests are about to be executed
session.getLauncher().registerTestExecutionListeners(new TestExecutionListener() {
@Override
public void testPlanExecutionStarted(TestPlan testPlan) {
if (fixture == null) {
fixture = new Fixture();
fixture.setUp();
}
}
});
}

@Override
public void launcherSessionClosed(LauncherSession session) {
if (fixture != null) {
fixture.tearDown();
fixture = null;
}
}

static class Fixture {

private HttpServer server;
private ExecutorService executorService;

void setUp() {
try {
server = HttpServer.create(new InetSocketAddress(0), 0);
}
catch (IOException e) {
throw new UncheckedIOException("Failed to start HTTP server", e);
}
server.createContext("/test", exchange -> {
exchange.sendResponseHeaders(204, -1);
exchange.close();
});
executorService = Executors.newCachedThreadPool();
server.setExecutor(executorService);
server.start(); // <1>
int port = server.getAddress().getPort();
System.setProperty("http.server.port", String.valueOf(port)); // <2>
}

void tearDown() {
server.stop(0); // <3>
executorService.shutdownNow();
}
}

}
//end::user_guide[]
35 changes: 35 additions & 0 deletions documentation/src/test/java/example/session/HttpTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2015-2021 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/

package example.session;

//tag::user_guide[]
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.net.HttpURLConnection;
import java.net.URL;

import org.junit.jupiter.api.Test;

class HttpTests {

@Test
void respondsWith204() throws Exception {
String port = System.getProperty("http.server.port"); // <1>
URL url = new URL("http://localhost:" + port + "/test");

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode(); // <2>

assertEquals(204, responseCode); // <3>
}
}
//end::user_guide[]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
example.session.GlobalSetupTeardownListener

0 comments on commit b6dff0d

Please sign in to comment.