我采用了现有的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
如果你运行激活器测试,你应该看到控制器测试中的错误。
答案 0 :(得分:1)
我遇到了完全相同的问题。我花了一点时间研究它,看来通过FakeRequest#withSession
,你可以最终调用游戏中Crypto
库的某些部分依赖于配置而无法传入FakeApplication
。
...但我找到了一个可能对您有用的简单解决方法。基本上只是用模拟间谍包装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
}
}
答案 1 :(得分:0)
看起来你没有在application.conf中配置play secret 你能尝试定义吗?
在这里查看更多details