!htk change return type of TestResponse.fail to Unit to avoid surprises for Java implementors

This commit is contained in:
Johannes Rudolph 2015-08-13 10:14:12 +02:00
parent 560785eaaa
commit 44ed8afd49
4 changed files with 39 additions and 13 deletions

View file

@ -7,19 +7,20 @@ package akka.http.javadsl.testkit
import akka.actor.ActorSystem
import akka.http.javadsl.server._
import akka.http.scaladsl.model.HttpResponse
import akka.stream.ActorMaterializer
import akka.stream.{ Materializer, ActorMaterializer }
import org.junit.rules.ExternalResource
import org.junit.{ Assert, Rule }
import scala.concurrent.duration._
/**
* A RouteTest that uses JUnit assertions.
* A RouteTest that uses JUnit assertions. ActorSystem and Materializer are provided as an [[ExternalResource]]
* and their lifetime is automatically managed.
*/
abstract class JUnitRouteTestBase extends RouteTest {
protected def systemResource: ActorSystemResource
implicit def system: ActorSystem = systemResource.system
implicit def materializer: ActorMaterializer = systemResource.materializer
implicit def materializer: Materializer = systemResource.materializer
protected def createTestResponse(response: HttpResponse): TestResponse =
new TestResponse(response, awaitDuration)(system.dispatcher, materializer) {
@ -32,7 +33,7 @@ abstract class JUnitRouteTestBase extends RouteTest {
protected def assertTrue(predicate: Boolean, message: String): Unit =
Assert.assertTrue(message, predicate)
protected def fail(message: String): Nothing = {
protected def fail(message: String): Unit = {
Assert.fail(message)
throw new IllegalStateException("Assertion should have failed")
}

View file

@ -7,7 +7,7 @@ package akka.http.javadsl.testkit
import scala.annotation.varargs
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import akka.stream.ActorMaterializer
import akka.stream.Materializer
import akka.http.scaladsl.server
import akka.http.javadsl.model.HttpRequest
import akka.http.javadsl.server.{ HttpApp, AllDirectives, Route, Directives }
@ -19,9 +19,17 @@ import akka.actor.ActorSystem
import akka.event.NoLogging
import akka.http.impl.util._
/**
* A base class to create route tests for testing libraries. An implementation needs to provide
* code to provide and shutdown an [[ActorSystem]], [[Materializer]], and [[ExecutionContext]].
* Also an implementation should provide instances of [[TestResponse]] to define the assertion
* facilities of the testing library.
*
* See `JUnitRouteTest` for an example of a concrete implementation.
*/
abstract class RouteTest extends AllDirectives {
implicit def system: ActorSystem
implicit def materializer: ActorMaterializer
implicit def materializer: Materializer
implicit def executionContext: ExecutionContext = system.dispatcher
protected def awaitDuration: FiniteDuration = 500.millis
@ -53,7 +61,7 @@ abstract class RouteTest extends AllDirectives {
/**
* Creates a [[TestRoute]] for the main route of an [[HttpApp]].
*/
def testAppRoute(app: HttpApp): TestRoute = testRoute(app.createRoute)
def testAppRoute(app: HttpApp): TestRoute = testRoute(app.createRoute())
protected def createTestResponse(response: HttpResponse): TestResponse
}

View file

@ -8,7 +8,7 @@ import scala.reflect.ClassTag
import scala.concurrent.ExecutionContext
import scala.concurrent.duration.FiniteDuration
import akka.util.ByteString
import akka.stream.ActorMaterializer
import akka.stream.Materializer
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.model.HttpResponse
import akka.http.impl.util._
@ -18,9 +18,12 @@ import akka.http.javadsl.server.Unmarshaller
import akka.http.javadsl.model._
/**
* A wrapper for responses
* A wrapper for responses.
*
* To support the testkit API, a third-party testing library needs to implement this class and provide
* implementations for the abstract assertion methods.
*/
abstract class TestResponse(_response: HttpResponse, awaitAtMost: FiniteDuration)(implicit ec: ExecutionContext, materializer: ActorMaterializer) {
abstract class TestResponse(_response: HttpResponse, awaitAtMost: FiniteDuration)(implicit ec: ExecutionContext, materializer: Materializer) {
/**
* Returns the strictified entity of the response. It will be strictified on first access.
*/
@ -75,7 +78,7 @@ abstract class TestResponse(_response: HttpResponse, awaitAtMost: FiniteDuration
*/
def header[T <: HttpHeader](clazz: Class[T]): T =
response.header(ClassTag(clazz))
.getOrElse(fail(s"Expected header of type ${clazz.getSimpleName} but wasn't found."))
.getOrElse(doFail(s"Expected header of type ${clazz.getSimpleName} but wasn't found."))
/**
* Assert on the numeric status code.
@ -150,7 +153,7 @@ abstract class TestResponse(_response: HttpResponse, awaitAtMost: FiniteDuration
}
private[this] def extractFromResponse[T](f: HttpResponse T): T =
if (response eq null) fail("Request didn't complete with response")
if (response eq null) doFail("Request didn't complete with response")
else f(response)
protected def assertEqualsKind(expected: AnyRef, actual: AnyRef, kind: String): TestResponse = {
@ -162,7 +165,13 @@ abstract class TestResponse(_response: HttpResponse, awaitAtMost: FiniteDuration
this
}
protected def fail(message: String): Nothing
// allows to `fail` as an expression
private def doFail(message: String): Nothing = {
fail(message)
throw new IllegalStateException("Shouldn't be reached")
}
protected def fail(message: String): Unit
protected def assertEquals(expected: AnyRef, actual: AnyRef, message: String): Unit
protected def assertEquals(expected: Int, actual: Int, message: String): Unit
protected def assertTrue(predicate: Boolean, message: String): Unit

View file

@ -7,6 +7,14 @@ package akka.http.javadsl.testkit
import akka.http.javadsl.model.HttpRequest
import akka.http.javadsl.server.Route
/**
* A wrapped route that has a `run` method to run a request through the underlying route to create
* a [[TestResponse]].
*
* A TestRoute is created by deriving a test class from the concrete RouteTest implementation for your
* testing framework (like [[JUnitRouteTest]] for JUnit) and then using its `testRoute` method to wrap
* a route with testing support.
*/
trait TestRoute {
def underlying: Route
def run(request: HttpRequest): TestResponse