2017-09-18 2 views
0

私はコントローラのアクションをテストしたいと思いますが、以下のエラーが表示されます。私は紛失する可能性がある小さなものがあるように感じますが、それが何であるかをはっきりと知ることができません。問題を説明するために小さなコードを書きました。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) 

は私が答えています、私は問題

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")) 
     } 
    ) 
    } 
} 

を説明するのを助けるために書いたコントローラとテストコード

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 
    } 
    } 
} 

私が使用していますプレイ2.6.3

答えて

0

ですこれは、同じ問題に直面する可能性のある他の人に利益をもたらす。

この問題を解決するために、スタブされたコントローラコンポーネントを(Helpers.stubControllerComponents()のように)注入する代わりに、inject[ControllerComponents]を使用しました。

基本的に、この問題を解決するために、コントローラコードは次のようになります。

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

テストクラスのGuiceOneAppPerSuiteで再生候補を拡張します。これで単体テストに使用できるアプリケーションのインスタンスが作成されます。

など。

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) 
    } 

    } 
} 

現在、このテストをプレイ2.6.1に使用しています。これが行うことは、アプリ全体のインスタンスを持つことになるので、1つずつインスタンス化することなくすべてのコントローラをテストすることができます。

+0

私のユースケースの問題を解決する方法を見つけ出し、それに直面する可能性のある他の人の質問に答えました。私がテストしているコントローラーには多くの依存関係があります。コントローラー固有のコードだけを単体テストしたいので、その機能をテストするときに手動でインスタンス化する必要があります。 – ivanorone

関連する問題