diff --git a/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingDemo.scala b/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingDemo.scala index 59ec733..c68aad1 100644 --- a/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingDemo.scala +++ b/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingDemo.scala @@ -69,7 +69,15 @@ object LogAccessRoutingDemo extends App { val exceptionRouteOrDemoArgs = demoArgs() val ( requestTimeoutInMillis, responseDelayInMillis) = exceptionRouteOrDemoArgs.right.getOrElse(1000L, 1000L) - val exceptionRouteOrDelayedResponse:Either[Route,DelayedResponse] = exceptionRouteOrDemoArgs.right.map(_ => DelayedResponse(responseDelayInMillis, "hello")) + + val serviceActorProps = { + exceptionRouteOrDemoArgs.fold( route => { + RouteServiceActor.apply(new DemoAccessLogger, route, "hello") + }, tupleArgs => { + DelayedResponseServiceActor.apply(new DemoAccessLogger, DelayedResponse(tupleArgs._2), "hello") + }) + } + val config = ConfigFactory.parseString( s""" |spray.can { @@ -85,9 +93,7 @@ object LogAccessRoutingDemo extends App { implicit val system = ActorSystem("log-access-routing-demo", config) - val serviceActor = system.actorOf(Props( - new TestLogAccessRoutingActor(new DemoAccessLogger, exceptionRouteOrDelayedResponse, "hello")) - ) + val serviceActor = system.actorOf(serviceActorProps) val serverStartedFuture = IO(Http).ask(Http.Bind(serviceActor, "localhost", 8085)).flatMap { diff --git a/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingTests.scala b/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingTests.scala index 4eb9266..915ef58 100644 --- a/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingTests.scala +++ b/src/test/scala/org/caoilte/spray/routing/LogAccessRoutingTests.scala @@ -1,5 +1,6 @@ package org.caoilte.spray.routing +import org.caoilte.spray.routing.TestAccessLogger.{AccessAlreadyLogged, LogAccess, LogEvent} import org.scalatest.FlatSpec import akka.testkit.TestKit import com.typesafe.config.ConfigFactory @@ -36,7 +37,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { it should "'Log Access' with a 200 response and an Access Time less than the request timeout" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 4000, - routeOrDelayedResponse = Right(DelayedResponse(500))) { testKit => + httpServiceActorFactory = DelayedResponseServiceActor.factory(DelayedResponse(500), PATH)) { testKit => import testKit._ whenReady(makeHttpCall(), timeout(Span(2, Seconds))) { s => @@ -59,7 +60,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { it should "'Log Access' with a 500 response and an Access Time less than the request timeout" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 4000, - routeOrDelayedResponse = Left(FailureRoutes.exceptionRoute)) { testKit => + httpServiceActorFactory = RouteServiceActor.factory(FailureRoutes.exceptionRoute, PATH)) { testKit => import testKit._ @@ -82,7 +83,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { it should "'Log Access' with a 500 response and an Access Time less than the request timeout" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 4000, - routeOrDelayedResponse = Left(FailureRoutes.failureRoute)) { testKit => + httpServiceActorFactory = RouteServiceActor.factory(FailureRoutes.failureRoute, PATH)) { testKit => import testKit._ @@ -106,7 +107,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { "and then 'Access already logged' with a 200 response and an Access Time more than the Request Timeout time" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 50, - routeOrDelayedResponse = Right(DelayedResponse(500))) { testKit => + httpServiceActorFactory = DelayedResponseServiceActor.factory(DelayedResponse(500), PATH)) { testKit => import testKit._ whenReady(makeHttpCall(), timeout(Span(2, Seconds))) { s => @@ -136,7 +137,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { "appropriate error message" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 10, - routeOrDelayedResponse = Right(DelayedResponse(2000))) { testKit => + httpServiceActorFactory = DelayedResponseServiceActor.factory(DelayedResponse(2000), PATH)) { testKit => import testKit._ @@ -169,7 +170,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { it should "'Log Access' for a request with an unacceptable Accept header by making a 406 response with an Access Time less than the request timeout" in { aTestLogAccessRoutingActor( requestTimeoutMillis = 4000, - routeOrDelayedResponse = Right(DelayedResponse(50))) { testKit => + httpServiceActorFactory = DelayedResponseServiceActor.factory(DelayedResponse(50), PATH)) { testKit => import testKit._ whenReady(makeHttpCall(MediaTypes.`application/json`), timeout(Span(2, Seconds))) { s => @@ -196,22 +197,8 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { val PATH = "test" val URI:Uri = Uri(s"$HOST/$PATH") - sealed trait LogType - case object LogAccess extends LogType - case object AccessAlreadyLogged extends LogType - case class LogEvent(request: HttpRequest, response: HttpResponse, time: Long, logAccessType: LogType) - - class TestAccessLogger(listener:ActorRef) extends AccessLogger { - override def logAccess(request: HttpRequest, response: HttpResponse, time: Long) = { - listener ! LogEvent(request, response, time, LogAccess) - } - - override def accessAlreadyLogged(request: HttpRequest, response: HttpResponse, time: Long) = { - listener ! LogEvent(request, response, time, AccessAlreadyLogged) - } - } // going to have to use 'request-timeout = infinite' - spray-can timeout handling is FUBAR def CONFIG(requestTimeout:String = "1 s") = @@ -234,7 +221,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { def aTestLogAccessRoutingActor( requestTimeoutMillis:Long, - routeOrDelayedResponse:Either[Route,DelayedResponse] + httpServiceActorFactory: TestKit => Props ) (callback: TestKit => Unit) { val config = ConfigFactory.parseString(CONFIG(s"$requestTimeoutMillis ms")) @@ -242,10 +229,7 @@ class LogAccessRoutingTests extends FlatSpec with ScalaFutures { val testKit = new TestKit(system) try { - val accessLogger = new TestAccessLogger(testKit.testActor) - val serviceActor = system.actorOf(Props( - new TestLogAccessRoutingActor(accessLogger, routeOrDelayedResponse, PATH)) - ) + val serviceActor = system.actorOf(httpServiceActorFactory(testKit)) val sprayServerStartResult = IO(Http).ask(Http.Bind(serviceActor, "localhost", PORT)).flatMap { case b: Http.Bound ⇒ Future.successful(b) diff --git a/src/test/scala/org/caoilte/spray/routing/TestLogAccessRoutingActor.scala b/src/test/scala/org/caoilte/spray/routing/TestLogAccessRoutingActor.scala index edcb558..f102350 100644 --- a/src/test/scala/org/caoilte/spray/routing/TestLogAccessRoutingActor.scala +++ b/src/test/scala/org/caoilte/spray/routing/TestLogAccessRoutingActor.scala @@ -1,6 +1,8 @@ package org.caoilte.spray.routing -import spray.http.{HttpEntity, ContentTypes} +import akka.testkit.TestKit +import org.caoilte.spray.routing.TestAccessLogger.TestAccessLogger +import spray.http.{HttpResponse, HttpRequest, HttpEntity, ContentTypes} import spray.routing._ import akka.actor.{Props, ActorRef, Actor} import scala.concurrent._ @@ -8,15 +10,43 @@ import akka.pattern.ask import akka.util.Timeout import java.util.concurrent.TimeUnit +object TestAccessLogger { + sealed trait LogType + case object LogAccess extends LogType + case object AccessAlreadyLogged extends LogType + + case class LogEvent(request: HttpRequest, response: HttpResponse, time: Long, logAccessType: LogType) + + class TestAccessLogger(listener:ActorRef) extends AccessLogger { + override def logAccess(request: HttpRequest, response: HttpResponse, time: Long) = { + listener ! LogEvent(request, response, time, LogAccess) + } + + override def accessAlreadyLogged(request: HttpRequest, response: HttpResponse, time: Long) = { + listener ! LogEvent(request, response, time, AccessAlreadyLogged) + } + } +} + + case object DelayedResponse { val DEFAULT_RESPONSE = "response" } case class DelayedResponse(thinkingMillis: Long, responseMessage:String = DelayedResponse.DEFAULT_RESPONSE) -class TestLogAccessRoutingActor(val accessLogger: AccessLogger, - routeOrDelayedResponse:Either[Route,DelayedResponse], path:String) +object DelayedResponseServiceActor { + def factory(delayedResponse: DelayedResponse, path:String): (TestKit => Props) = testKit => { + apply(new TestAccessLogger(testKit.testActor), delayedResponse, path) + } + def apply(accessLogger: AccessLogger, delayedResponse: DelayedResponse, path:String):Props = { + Props(new DelayedResponseServiceActor(accessLogger, delayedResponse, path)) + } +} + +class DelayedResponseServiceActor(val accessLogger: AccessLogger, delayedResponse: DelayedResponse, path:String) extends HttpServiceActor with LogAccessRoutingActor { + case object RequestForDelayedResponse @@ -37,25 +67,42 @@ class TestLogAccessRoutingActor(val accessLogger: AccessLogger, implicit def executionContext = actorRefFactory.dispatcher override def preStart { - routeOrDelayedResponse.right.map( response => { - testAc = context.actorOf(Props(new DelayedResponseActor(response)), "delayed-response-test-actor") - }) + testAc = context.actorOf(Props(new DelayedResponseActor(delayedResponse)), "delayed-response-test-actor") super.preStart } val routes:Route = { path(path) { get { - routeOrDelayedResponse match { - case Left(route) => route - case Right(DelayedResponse(thinkingMillis, _)) => { - implicit val TIMEOUT: Timeout = Timeout(thinkingMillis * 2, TimeUnit.MILLISECONDS) - complete((testAc ? RequestForDelayedResponse).mapTo[HttpEntity]) - } - } + implicit val TIMEOUT: Timeout = Timeout(delayedResponse.thinkingMillis * 2, TimeUnit.MILLISECONDS) + complete((testAc ? RequestForDelayedResponse).mapTo[HttpEntity]) } } } override def receive = runRoute(routes) } + + +object RouteServiceActor { + def factory(route: Route, path:String): (TestKit => Props) = testKit => { + apply(new TestAccessLogger(testKit.testActor), route, path) + } + def apply(accessLogger: AccessLogger, route: Route, path:String):Props = { + Props(new RouteServiceActor(accessLogger, route, path)) + } +} + +class RouteServiceActor(val accessLogger: AccessLogger, route: Route, path:String) + extends HttpServiceActor with LogAccessRoutingActor { + + val routes:Route = { + path(path) { + get { + route + } + } + } + + override def receive = runRoute(routes) +} \ No newline at end of file