2017-09-18 2 views
0

J'ai une action de contrôleur que je voudrais tester mais je reçois l'erreur ci-dessous. J'ai l'impression qu'il y a quelque chose de petit que je pourrais manquer, mais je n'arrive pas à comprendre ce que c'est. J'ai écrit un petit code pour illustrer le problème. Abit de plus de contexte, je voudrais être en mesure de fournir des dépendances fictives au contrôleur c'est pourquoi je suis en train de reprendre son instanciation.Test de l'unité de jeu actions du contrôleur qui ont des analyseurs json

java.lang.UnsupportedOperationException: NoMaterializer does not provide an ExecutionContext 
[info] at play.api.test.NoMaterializer$.executionContext(Helpers.scala:661) 
[info] at play.api.mvc.PlayBodyParsers.$anonfun$enforceMaxLength$1(BodyParsers.scala:866) 
[info] at akka.stream.impl.Compose.apply(TraversalBuilder.scala:164) 
[info] at akka.stream.impl.PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:488) 
[info] at akka.stream.impl.PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:424) 
[info] at akka.stream.impl.PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:415) 
[info] at akka.stream.scaladsl.RunnableGraph.run(Flow.scala:496) 

est en dessous du contrôleur je l'ai écrit pour illustrer le problème

case class Location(lat: Double, long: Double) 

object Location { 

    implicit val locationReads: Reads[Location] = (
    (JsPath \ "lat").read[Double](min(-90.0) keepAnd max(90.0)) and 
     (JsPath \ "long").read[Double](min(-180.0) keepAnd max(180.0)) 
    ) (Location.apply _) 
} 

class HomeController @Inject()(
    cc: ControllerComponents, 
    mat: Materializer 
)(implicit val ec: ExecutionContext) extends AbstractController(cc) { 


    def savePlace: Action[JsValue] = Action(parse.json) { request: Request[JsValue] => 
    val placeResult = request.body.validate[Location] 
    placeResult.fold(
     errors => { 
     BadRequest(Json.obj("status" -> "KO", "message" -> JsError.toJson(errors))) 
     }, 
     place => { 
     Ok(Json.obj("status" -> "OK", "message" -> "Location saved")) 
     } 
    ) 
    } 
} 

et le code de test

class HomeControllerSpec extends PlaySpec with Injecting with Inside with GuiceOneAppPerSuite with BeforeAndAfterEach with Results with BeforeAndAfterAll { 
    implicit lazy override val app: play.api.Application = new GuiceApplicationBuilder().configure().build() 
    implicit lazy val materializer: Materializer = app.materializer 
    implicit lazy val components = Helpers.stubControllerComponents() 

    "savePlace" must { 

    val api = new HomeController(components, mat = materializer) 

    val payload = Json.obj(
     "location" -> Json.obj("lat" -> 51.235685, "lng" -> -1.309197) 
    ) 

    "just demo" in { 
     val request = FakeRequest(POST, "/location").withJsonBody(payload) 

     val result = call(api.savePlace, request) 
     status(result) mustBe UNAUTHORIZED 
    } 
    } 
} 

J'utilise le jeu 2.6.3

Répondre

0

Je réponds cela profite à quelqu'un d'autre qui pourrait faire face au même problème.

Pour résoudre le problème, au lieu d'injecter des composants de contrôleur stubbed (comme dans Helpers.stubControllerComponents()), j'ai utilisé inject[ControllerComponents].

Fondamentalement, pour résoudre le problème, le code du contrôleur devrait maintenant ressembler à ceci.

class HomeControllerSpec 
    extends PlaySpec with Injecting with Inside with GuiceOneAppPerSuite with Results { 
    implicit lazy override val app: play.api.Application = new GuiceApplicationBuilder().configure().build() 
    implicit lazy val materializer = app.materializer 

    implicit lazy val components = inject[ControllerComponents] 

    "savePlace" must { 

    val api = new HomeController(components) 

    val payload = Json.obj("lat" -> 51.235685, "long" -> -1.309197) 

    "just demo" in { 
     val request = FakeRequest(POST, "/location").withJsonBody(payload) 

     val result = call(api.savePlace, request) 
     println(contentAsJson(result)) 
     status(result) mustBe UNAUTHORIZED 

    } 
    } 
} 
0

Etendez playspec avec GuiceOneAppPerSuite dans votre classe de test. Maintenant, vous aurez une instance d'une application que vous pouvez utiliser pour tester cette unité.

E.g.

class HomeSpec extends PlaySpec with GuiceOneAppPerSuite { 

    "Home" should { 

    "send 404 on a bad request" in { 
     route(app, FakeRequest(GET, "/boum")).map(status(_)) mustBe Some(
     NOT_FOUND) 
    } 

    "send 200 on a good request" in { 
     route(app, FakeRequest(GET, "/")).map(status(_)) mustBe Some(OK) 
    } 

    } 
} 

J'utilise actuellement ce test pour le jeu 2.6.1. Ce que cela va faire, c'est, vous aurez une instance de l'application entière, de sorte que vous pouvez tester tous les contrôleurs sans avoir à instancier un par un.

+0

Merci de m'avoir invité. J'ai trouvé comment résoudre le problème pour mon cas d'utilisation et j'ai répondu à la question pour quelqu'un d'autre qui pourrait y faire face aussi. Les contrôleurs que je suis en train de tester ont beaucoup de dépendances et je veux tester uniquement le code spécifique au contrôleur. J'ai donc besoin de les instancier manuellement un par un en testant leurs fonctionnalités. – ivanorone