使用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 play框架中对异步控制器进行单元测试的正确方法吗?
答案 0 :(得分:1)
我的一些建议是
contentAsJson
代替contentAsString
并检查返回的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>")
答案 1 :(得分:1)
默认情况下,播放操作是异步的。
这意味着,即使您没有使用Action.async { Future { myAnonymousFunction } }
而只使用Action { myAnonymousFunction }
,internally,myAnonymousFunction
的结果也会包含在Future
中。
例如,说你有
class HelloWorld extends Controller {
def index = Action { request => Ok("") }
}
然后
(new HelloWorld).index().apply(FakeRequest())
仍有类型
Future[Result]
这让我相信你的单元测试确实是测试控制器的合适方式,也就是说,Play的文档也隐含地涵盖了Action.async
的情况。