scala play 框架如何对异步 Controller 进行单元测试

标签 scala unit-testing asynchronous playframework

使用 Scala play 版本 2.5 并尝试按照文档遵循单元测试 Controller 的指南:https://www.playframework.com/documentation/2.5.x/ScalaTestingWithScalaTest

没有单元测试异步 Controller 的示例。

我正在尝试为我的 Controller 创建一个具有异步操作方法的单元测试,我最终模拟了一些对象

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 Play Framework 中对异步 Controller 进行单元测试的正确方法吗?

最佳答案

我的一些建议是

  • 使用 contentAsJson 而不是 contentAsString 并检查返回的 json。
  • 使用route 直接调用 Controller 并测试响应(例如route(app, FakeRequest..)
  • 使用status方法检查返回的状态是否为HTTPOK(状态码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>")
    

关于scala play 框架如何对异步 Controller 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44509708/

相关文章:

scala - scala中的反勾有什么用

scala - 测试中*的含义是什么?

javascript - Gulp,Mocha,观看不重新加载我的源文件

node.js - NodeJS : Breaking a large amount of synchronous tasks into async tasks

java程序转scala的互操作性问题

c# - 单元测试带有延迟计时器的响应式(Reactive)扩展方法

python - pytest 说当我不使用时找不到 fixture

winapi - ReadFile 在 Win7 和 Win2k8 上不能异步工作

javascript - 如何解决我的异步函数?

scala - Spark Streaming - 刷新静态数据