akka-http
akka-http copied to clipboard
Add docs for using testkits with Junit 5
Sister-ticket of akka/akka#27155
We since previously have a request to migrate to JUnit 5 but since the demand has been so low I'm not sure if we want to do that, however, I think we should show in docs how to use the testkit with JUnit 5
Alpakka Kafka has done this in the docs here https://doc.akka.io/docs/alpakka-kafka/current/testing.html#testing-from-java-code
I'm having a hard time getting akka-http testing setup in a project that already uses JUnit5 (and which wont will switch back to JUnit4 just cause of Akka-HTTP). Any pointers on something existing I can take a look at to get this running?
See also #1476
In a gradle build setup adding the vintage engine helped with the tests failing.
dependencies {
testImplementation("org.junit.vintage:junit-vintage-engine:5.8.2")
}
I still couldn't get testRoute() working, even with vintage-engine lib added. I ended up with custom base test class implementation. I'm sharing it here in case it helps someone:
import akka.http.javadsl.testkit.ActorSystemResource;
import akka.http.javadsl.testkit.JUnitRouteTestBase;
import com.typesafe.config.ConfigFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
public class RouteTestBase extends JUnitRouteTestBase {
private static final ActorSystemResource systemResource = new ActorSystemResource(
"TestSystem",
ConfigFactory.empty());
@BeforeAll
public static void before() {
systemResource.before();
}
@AfterAll
public static void after() {
systemResource.after();
}
@Override
public ActorSystemResource systemResource() {
return systemResource;
}
}
With this approach you still need
org.junit.vintage:junit-vintage-engineas someakka-http-teskitinternals depend on Junit4 classes.
The above was helpful, I'll add some details on what it took to get the akka-http-quickstart-java tests to run.
The dependencies + the surefire plugin:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<!-- JUnit 5 requires Surefire version 2.22.0 or higher -->
<version>2.22.0</version>
</plugin>
And the test:
package com.example;
import akka.actor.testkit.typed.javadsl.TestKitJunitResource;
import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.javadsl.Adapter;
import akka.http.javadsl.model.*;
import akka.http.javadsl.testkit.ActorSystemResource;
import akka.http.javadsl.testkit.JUnitRouteTestBase;
import akka.http.javadsl.testkit.TestRoute;
import com.typesafe.config.ConfigFactory;
import org.junit.ClassRule;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.model.StatusCodes;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class UserRoutesTest extends JUnitRouteTestBase {
private static final ActorSystemResource systemResource = new ActorSystemResource(
"TestSystem",
ConfigFactory.empty());
// shared registry for all tests
private static ActorRef<UserRegistry.Command> userRegistry;
private TestRoute appRoute;
@ClassRule
public static TestKitJunitResource testkit = new TestKitJunitResource();
@BeforeAll
public void before() {
systemResource.before();
ActorSystem<Void> typedActorSystem = Adapter.toTyped(systemResource.system());
userRegistry = testkit.spawn(UserRegistry.create());
UserRoutes userRoutes = new UserRoutes(typedActorSystem, userRegistry);
appRoute = testRoute(userRoutes.userRoutes());
}
@AfterAll
public static void after() {
systemResource.after();
}
@Override
public ActorSystemResource systemResource() {
return systemResource;
}
@Test
public void test1NoUsers() {
appRoute.run(HttpRequest.GET("/users"))
.assertStatusCode(StatusCodes.OK)
.assertMediaType("application/json")
.assertEntity("{\"users\":[]}");
}
@Test
public void test2HandlePOST() {
appRoute.run(HttpRequest.POST("/users")
.withEntity(MediaTypes.APPLICATION_JSON.toContentType(),
"{\"name\": \"Kapi\", \"age\": 42, \"countryOfResidence\": \"jp\"}"))
.assertStatusCode(StatusCodes.CREATED)
.assertMediaType("application/json")
.assertEntity("{\"description\":\"User Kapi created.\"}");
}
@Test
public void test3Remove() {
appRoute.run(HttpRequest.DELETE("/users/Kapi"))
.assertStatusCode(StatusCodes.OK)
.assertMediaType("application/json")
.assertEntity("{\"description\":\"User Kapi deleted.\"}");
}
}