akka - Why are implicit variables not initialized in Scala when called from unit test? -


given the following singleton object in scala:

package demo  import akka.actor.actorsystem import akka.http.scaladsl.http import akka.http.scaladsl.server.directives._ import akka.stream.actormaterializer  import scala.concurrent.future import scala.io.stdin  object webserver extends app {    implicit val system = actorsystem("myactorsystem")   implicit val executioncontext = system.dispatcher   implicit val materializer = actormaterializer()    val route = {     path("api" / "done-as-promised") {       {         complete {           future.successful("done")         }       }     }   }    val bindingfuture = http().bindandhandle(route, "localhost", 8080)  } 

and following unit test

package demo  import akka.http.scaladsl.testkit.scalatestroutetest import org.scalactic.typecheckedtripleequals import org.scalatest.{inspectors, matchers, wordspec}  class webserverspec extends wordspec matchers typecheckedtripleequals inspectors scalatestroutetest {    "the webserver /done-as-promised" should {     "return done" in {       // tests:       get("/api/done-as-promised") ~> webserver.route ~> check {         status.intvalue() shouldequal 200         responseas[string] shouldequal "done"       }     }   } } 

i following error:

[error] [04/19/2016 07:12:18.995] [scalatest-run-running-webserverspec] [akka.actor.actorsystemimpl(demo-webserverspec)] error during processing of request httprequest(httpmethod(get),http://example.com/api/done-as-promised,list(),httpentity.strict(none/none,bytestring()),httpprotocol(http/1.1)) java.lang.nullpointerexception @ akka.http.scaladsl.server.directives.executiondirectives$$anonfun$handleexceptions$1$$anonfun$apply$1.apply(executiondirectives.scala:33) @ akka.http.scaladsl.server.directives.executiondirectives$$anonfun$handleexceptions$1$$anonfun$apply$1.apply(executiondirectives.scala:29) @ akka.http.scaladsl.testkit.routetest$tildearrow$$anon$1.apply(routetest.scala:162) @ akka.http.scaladsl.testkit.routetest$tildearrow$$anon$1.apply(routetest.scala:150)

it took me while figure out. thing is: removing extends app make test succeed.

the reason problem when webserver declared extends app, uses delayedinit functionality of app trait. because of this, initialization code in contructor not added constructor of webserver object. instead called when main method called on webserver. when references "route" inside tests, coming null.

mixing in delayedinit trait (app extends delayedinit) rewrite class or object template. instead of adding val's , var's constructor, added def delayedinit(body: => unit) hook (inaccessible user code). apparently 1 called whenever main method called.

you can verify calling "main" on webserver inside test. if this, test pass. because calling main triggers initialization resulting in objects being created.

generally speaking though right solution move routing somewhere else, rather having inside of base app.


Comments

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -