2017-06-12 69 views
1

使用Scala的打版2.5,並試圖遵循單元測試控制器的指導方針按照文檔:https://www.playframework.com/documentation/2.5.x/ScalaTestingWithScalaTest斯卡拉發揮框架​​如何進行單元測試異步控制器

有單元測試異步控制器沒有例子。

我試圖創建我的控制器,它具有一個異步操作方法的單元測試,我結束了嘲諷某些對象

class ProductController @Inject()(
    action: ProductAction, 
    handler: ProductResourceHandler)(implicit ec: ExecutionContext) 
    extends Controller { 

    /** 
    * Fetch a list of products 
    */ 
    def index: Action[AnyContent] = { 
    action.async { implicit request => 
     handler.find.map { list =>         
     Ok(Json.toJson(list)) 
     } 
    } 
    } 
// ... 
} 

我的單元測試:

import scala.concurrent.Future 
import org.scalatestplus.play._ 
import play.api.mvc._ 
import play.api.test._ 
import play.api.test.Helpers._ 
import org.scalatest.mockito.MockitoSugar 
import product.ProductAction 
import product.ProductController 
import product.services.maps.GeolocationService 
import product.ProductResourceHandler 
import play.api.libs.concurrent.Execution.Implicits._ 
import scala.io.Source 
import play.api.libs.json.Json 
import product.model.OfferList 
import product.model.OfferDetail 
import org.mockito.Mockito._ 

class ProductControllerSpec extends PlaySpec with Results with MockitoSugar { 

    private val productList = Json.parse(Source.fromFile("conf/app/sample_products.json").getLines.mkString).as[ProductList] 

    "Example Page#index" should { 
    "should be valid" in { 
     val action = new ProductAction() 
     val handler = mock[ProductResourceHandler]  
     when(handler.find) thenReturn Future.successful(productList)  
     val controller = new ProductController(action, handler) 
     val result: Future[Result] = controller.index().apply(FakeRequest())  
     val bodyText: String = contentAsString(result)         
     bodyText != null mustBe true 
    } 
    } 
} 

到現在它正在工作,但我想知道這是否遵循這種類型的測試的最佳做法或指導方針。這是在Scala播放框架中單元測試異步控制器的正確方法嗎?

回答

1

我的一些建議是不是contentAsString

  • 使用contentAsJson並檢查返回的JSON。
  • 使用route直接調用控制器和測試響應(對於例如route(app, FakeRequest..
  • 使用status方法來檢查返回的狀態是HTTP OK(狀態碼200)

    val Some(result) = route(app, FakeRequest(GET, 
              controllers.routes. ProductController.index.path())) 
    status(result) must be (OK) 
    val json = contentAsJson(result) 
    // inspect json fields like if you have to check if the json 
    // has string field called id you can do (json \ "id").as[String] must be ("<id value>") 
    
+0

你的輸入是合適的,對於使用路由器對象的第一點什麼是應用程序實例,我將如何注入它?我目前按照Scala Play測試文檔中的示例進行操作:https://www.playframework.com/documentation/2.5.x/ScalaTestingWithScalaTest其中示例不使用路由器,但直接調用控制器方法 – guilhebl

+0

mixin特性'OneAppPerSuite'到你的測試班。它爲您的應用程序實例注入。具有此特徵的每個套件都會創建一個App實例。 –

+0

查看官方發佈文檔的示例:https://www.playframework.com/documentation/2.5.x/ScalaTestingWithScalaTest。儘管我同意使用contentAsJson檢查JSON結果,但現在有用的是,其他兩點與官方play文檔如何描繪樣本控制器單元測試並不一致,而您在https:// www中列出了您建議的mixin「OneAppPerSuite」 .playframework.com/documentation/2.5.x/ScalaFunctionalTestingWithScalaTest與功能測試相關 – guilhebl

1

根據到Play documentation

播放操作通過預設噸。

這即使你不使用Action.async { Future { myAnonymousFunction } }只是Action { myAnonymousFunction }internallymyAnonymousFunction結果將被封閉在Future手段。

舉例來說,假設你有

class HelloWorld extends Controller { 
    def index = Action { request => Ok("") } 
} 

然後

(new HelloWorld).index().apply(FakeRequest()) 

仍然有鍵入

Future[Result] 

這使我相信,你的單元測試確實測試的適當方式控制器,也就是說,Play的文檔也隱含地涵蓋了的情況。