2013-10-18 8 views
12

コントローラをテストしようとしていますが、これは新しいAction.asyncを使用しています。 documentation以下の私は、私は型を参照して別の形質にテストしたいコントローラの下の部分を除外している:それは動作しますindex()方法についてAction.asyncを使用してコントローラをテストできません

object UsersControllerSpec extends PlaySpecification with Results { 
    class TestController() extends Controller with UserController 
    "index action" should { 
     "should be valid" in { 
     val controller = new TestController() 
     val result: Future[SimpleResult] = controller.index().apply(FakeRequest()) 
     /* assertions */ 
     } 
    } 
    } 
} 

:私は次のようにそれをテストすることになってる

trait UserController { this: Controller => 
    def index() = Action { /* snip */ } 
    def register() = Action.async(parse.json) { request => /* snip */ } 
} 

ドキュメントの状態完全に、残念ながらregister()と同じことをすることはできません.FakeRequestを適用すると、Iteratee[Array[Byte], SimpleResult]のインスタンスが返されます。私はそれがFuture[SimpleResult]を返すrun()メソッドを持っていることに気づいたが、FakeRequestそれはどんな内容やヘッダーもなしで400と返す。 FakeRequestの内容が私には全く見られないようです。どういうわけかiterateeにリクエストボディを送り、それを実行するはずですか?どのように私はそれを行うことができますどのような例を見つけることができませんでした。私にとって

+0

これで運を?それは私を夢中にさせている! – benburton

答えて

6

はこれを動作します:

import concurrent._ 
import play.api.libs.json._ 
import play.api.mvc.{SimpleResult, Results, Controller, Action} 
import play.api.test._ 
import ExecutionContext.Implicits.global 

trait UserController { 
    this: Controller => 
    def index() = Action { 
    Ok("index") 
    } 

    def register() = Action.async(parse.json) { 
    request => 
     future(Ok("register: " + request.body)) 
    } 
} 

object UsersControllerSpec extends PlaySpecification with Results { 

    class TestController() extends Controller with UserController 

    "register action" should { 
    "should be valid" in { 
     val controller = new TestController() 
     val request = FakeRequest().withBody(Json.obj("a" -> JsString("A"), "b" -> JsString("B"))) 
     val result: Future[SimpleResult] = controller.register()(request) 
     /* assertions */ 
     contentAsString(result) === """register: {"a":"A","b":"B"}""" 
    } 
    } 
} 
+0

私の安全な行動のために同様の問題が発生していますが、似たような解決策がありますか? @stackoverflow.com/questions/26303705/secured-trait-causing-spec2-unit-test-compilation-errors –

+5

これに加えてさらに@ tjdettのコメントには、 'withJsonBody'が' FakeRequest [ AnyContentAsJson] 'ではなく、' FakeRequest [JsValue] 'ではありません。だから 'withJsonBody'を使わず、' withBody'を使ってください。 – healsjnr

8

play.api.mvc.Action[A]は、これら2つの方法を適用含まれているため、この問題が発生する:

// What you're hoping for 
def apply(request: Request[A]): Future[Result] 

// What actually gets called 
def apply(rh: RequestHeader): Iteratee[Array[Byte], Result] 

これは、この場合には理由Request[A] extends RequestHeader、およびAを発生するすべての違いになります。正しいタイプでない場合は、間違ってapplyと呼ぶことになります。

ActionBuilderBodyParser[A]を使用すると、Action[A]が作成されます。その結果、テストするにはRequest[A]が必要になります。 parse.jsonBodyParser[JsValue]を返しますので、Request[JsValue]が必要です。

// In FakeRequest object 
def apply(): FakeRequest[AnyContentAsEmpty.type] 

FakeRequest()必要なタイプが得られません。幸いなこと:

// In FakeRequest class 
def withBody[B](body: B): FakeRequest[B] 

ので、体のためのプレースホルダを使用してテストを書き始める:

"should be valid" in { 
    val controller = new TestController() 
    val body: JsValue = ??? // Change this once your test compiles 

    // Could do these lines together, but this shows type signatures 
    val request: Request[JsValue] = FakeRequest().withBody(body) 
    val result: Future[Result] = controller.index().apply(request) 

    /* assertions */ 
    } 
関連する問題