2013-10-18 16 views
12

kullanarak denetleyiciyi test edemiyorum Yeni Action.async kullanan denetleyiciyi sınamaya çalışıyorum.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 */ 
     } 
    } 
    } 
} 

index() yöntemi için çalışır: ben bunu test etmek gerekiyor

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

Belgeleme devletler: Ben denetleyicisi altında kısmını hariç tutmuş documentation ardından ben tip atfen ayrı özellik ile test etmek istiyorum Maalesef, ile aynı işlemi yapamıyorum, FakeRequest'i uygularken Iteratee[Array[Byte], SimpleResult] örneğini döndürür. Ben Future[SimpleResult] döndüren run() yöntemi vardır farkettim, ancaknasıl olursa olsun hiçbir içerik veya başlık olmadan 400 ile döner. Bana FakeRequest içeriği gibi göz ardı ediliyor gibi gözüküyor. İstek gövdesini bir şekilde yinelemeli ve sonra çalıştırmam gerekiyor mu? Hiçbir örnek bulamadım bunu nasıl yapabilirim. Benim için

+0

bu buIdun? Bu beni delirtiyor! – benburton

cevap

6

bu çalışır: Bunun nedeni Request[A] extends RequestHeader doğar

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

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

ve bu durumda A tüm farkı yaratan: play.api.mvc.Action[A] bu iki yöntem uygulanır içerdiğinden

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

Güvenli işlemlerim için benzer problemler alıyorum, benzer bir çözüm var mı? http://stackoverflow.com/questions/26303705/secured-trait-causing-spec2-unit-test-compilation-errors –

+5

Bunun üzerine bir gotcha ve @ tjdett'in yorumları, 'jsonbody ile bir 'FakeRequest [ AnyContentAsJson] ', FakeRequest [JsValue]' değil. Yani 'JsonBody' ile kullanmayın,' withBody' kullanın. – healsjnr

8

Bu sorun ortaya çıkar. Doğru tür değilse, yanlış apply numaralı çağrıyı sonlandırırsınız.

BodyParser[A] ile ActionBuilder'u kullandığınızda, bir Action[A] oluşturun. Sonuç olarak, test etmek için bir Request[A] gerekir. parse.json, BodyParser[JsValue] değerini döndürür, bu nedenle bir Request[JsValue] gerekir.

FakeRequest() size ihtiyacınız olan türü almaz. Neyse:

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

Yani, vücut için bir yer tutucu kullanarak testini yazmaya başlamak:

"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 */ 
    }