使用扩展控制器播放 2.4 macwire 示例似乎无法模拟



我以现有的Macwire为例,并像这样扩展了控制器CoffeeController.scala

package com.softwaremill.play24.controllers
import com.softwaremill.play24.dao.CoffeeDao
import play.api.i18n.Lang
import play.api.libs.json.Json
import play.api.mvc._
import scala.concurrent.{Future}
import play.api.libs.concurrent.Execution.Implicits.defaultContext
import play.api.mvc.Results._
class CoffeeController(
  coffeeDao: CoffeeDao
)(implicit ec: SomeContextBuilder) extends AnotherController {
  def fetchAll() = DecoratedAction() { request =>
    coffeeDao.all.map { coffees =>
      Ok(Json.toJson(coffees))
    }
  }
  def priced(price: Double) = ResolvedDecoratedAction() { request =>
    coffeeDao.byPriceWithSuppliers(price).map { result =>
      Ok(Json.toJson(result.toMap))
    }
  }
}
trait ContextBuilder[U <: TraitLike] {
  def build(request: Request[AnyContent]): Future[Either[Result, RequestWithContext[U]]]
  def buildAuthenticated(request: Request[AnyContent]): Future[Either[Result, RequestWithResolvedContext[U]]]
}
trait TraitLike {
  def id: String
}
trait WithSessionId {
  self: RequestHeader =>
  lazy val sessionId = self.session.get("auth").getOrElse(java.util.UUID.randomUUID().toString)
}
case class RequestWithContext[U <: TraitLike](request: Request[AnyContent], lang: Lang, anything: Option[U]) extends WrappedRequest(request) with WithSessionId
case class RequestWithResolvedContext[U <: TraitLike](request: Request[AnyContent], lang: Lang, anything: U, rememberMe: Boolean = false) extends WrappedRequest(request) with WithSessionId
case class Trait(val id: String) extends TraitLike
class AnotherController[U <: TraitLike](implicit ctxBuilder: ContextBuilder[U]) extends Controller  {
  def DecoratedAction(bodyParser: BodyParser[AnyContent] = parse.anyContent)(f: RequestWithContext[U] => Future[Result]) = Action.async {
    implicit request =>
      ctxBuilder.build(request) flatMap {
        case Left(r) =>
          Future.successful(r)
        case Right(requestContext) =>
          f(requestContext).map(_.addingToSession( ("auth" , requestContext.sessionId) ))
      }
  }
  def ResolvedDecoratedAction(bodyParser: BodyParser[AnyContent] = parse.anyContent)(f: RequestWithResolvedContext[U] => Future[Result]) = Action.async {
    implicit request =>
      ctxBuilder.buildAuthenticated(request) flatMap {
        case Left(r) =>
          Future.successful(r)
        case Right(requestContext) =>
          f(requestContext).map(_.addingToSession( ("auth", requestContext.sessionId) ))
      }
  }
}
class SomeContextBuilder extends ContextBuilder[TraitLike] {
  override def build(request: Request[AnyContent]): Future[Either[Result, RequestWithContext[TraitLike]]] = Future.successful(Right(RequestWithContext(request, Lang("en-us"),None)))
  override def buildAuthenticated(request: Request[AnyContent]): Future[Either[Result, RequestWithResolvedContext[TraitLike]]] = Future.successful(Right(RequestWithResolvedContext(request, Lang("en-us"),Trait("id"),false)))
}

ControllerModule.scala

package com.softwaremill.play24.modules
import com.softwaremill.macwire._
import com.softwaremill.play24.controllers.{SomeContextBuilder, SupplierController, CoffeeController}
import com.softwaremill.play24.dao.{CoffeeDao, SupplierDao}
import play.api.libs.ws.WSClient
import scala.concurrent.ExecutionContext
trait ControllerModule {
  // Dependencies
  implicit def ec: ExecutionContext
  implicit val ctxBuilder = wire[SomeContextBuilder]
  def wsClient: WSClient
  def supplierDao: SupplierDao
  def coffeeDao: CoffeeDao
  // Controllers
  lazy val supplierController = wire[SupplierController]
  lazy val coffeeController = wire[CoffeeController]
}

但是,当我运行测试时,我得到了堆栈跟踪:

[error]   ! return priced by coffee, supplier
  [error]    No configuration setting found for key 'play.crypto.secret' (SimpleConfig.java:152)
[error] com.typesafe.config.impl.SimpleConfig.findKeyOrNull(SimpleConfig.java:152)
[error] com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:170)
[error] com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:176)
[error] com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:176)
[error] com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:193)
[error] com.typesafe.config.impl.SimpleConfig.findOrNull(SimpleConfig.java:198)
[error] com.typesafe.config.impl.SimpleConfig.getIsNull(SimpleConfig.java:208)
[error] play.api.PlayConfig.getOptional(Configuration.scala:951)
[error] play.api.PlayConfig.getOptionalDeprecated(Configuration.scala:996)
[error] play.api.libs.CryptoConfigParser.get$lzycompute(Crypto.scala:232)
[error] play.api.libs.CryptoConfigParser.get(Crypto.scala:203)
[error] play.api.libs.Crypto$$anonfun$crypto$1.apply(Crypto.scala:42)
[error] play.api.libs.Crypto$$anonfun$crypto$1.apply(Crypto.scala:40)
[error] play.api.libs.Crypto$.crypto(Crypto.scala:43)
[error] play.api.libs.Crypto$.sign(Crypto.scala:67)
[error] play.api.mvc.CookieBaker$class.encode(Http.scala:502)
[error] play.api.mvc.Session$.encode(Http.scala:651)
[error] play.api.mvc.CookieBaker$class.encodeAsCookie(Http.scala:554)
[error] play.api.mvc.Session$.encodeAsCookie(Http.scala:651)
[error] play.api.mvc.Result.withSession(Results.scala:170)
[error] play.api.mvc.Result.addingToSession(Results.scala:262)
[error] com.softwaremill.play24.controllers.AnotherController$$anonfun$ResolvedDecoratedAction$1$$anonfun$apply$5$$anonfun$apply$6.apply(CoffeeController.scala:64)
[error] com.softwaremill.play24.controllers.AnotherController$$anonfun$ResolvedDecoratedAction$1$$anonfun$apply$5$$anonfun$apply$6.apply(CoffeeController.scala:64)

我可以尝试运行(FakeApplication()){...},但随后我收到路由注入器错误。 目前代码在build.sbt中使用routesGenerator := InjectedRoutesGenerator,但我认为它不会转化为测试阶段。

我已经把代码放在这里https://github.com/tashiscool/Play24MacwireMockingFailure

如果运行激活器测试,则应在控制器测试中看到错误。

我遇到了完全相同的问题。 我花了一些时间研究它,似乎通过 FakeRequest#withSession ,您最终可以在 play 中调用 Crypto 库的某些部分,这些部分依赖于 config 但无法传入FakeApplication

。但我确实找到了一个简单的解决方法,也可能对您有用。基本上只是用 mockito 间谍包装FakeRequest,然后存根尝试调用内部 Crypto API 的方法。

import org.mockito.Mockito.{doReturn, spy}
import play.api.mvc.{AnyContentAsEmpty, Session}
import play.api.test.FakeRequest
trait AuthSupport { 
  def fakeRequest(): FakeRequest[AnyContentAsEmpty.type] = {
    val request = spy(FakeRequest())
    doReturn(Session(Map("userId" -> "1"))).when(request).session
    request
  }
}

看起来您没有在 application.conf
中配置游戏密钥你能试着定义一下吗?

查看此处了解更多详情

最新更新