【问题标题】:specs2 mock methods in a scala trait never verified从未验证过的 Scala 特征中的 specs2 模拟方法
【发布时间】:2018-06-15 01:37:00
【问题描述】:

我正在尝试模拟我与外部 API 的交互,该 API 检查令牌以查看用户是否被授权执行某些操作(它目前是作为 PoC 的单独 API,稍后将被移动到中间件中)

依赖项(SBT DSL)

"org.specs2" %% "specs2-core" % "4.2.0" % Test,
"org.specs2" %% "specs2-mock" % "4.2.0" % Test

测试

class MyHandlerSpec extends Specification with Mockito {
   def is = s2"""
     The first step is to check if the lambda is called on behalf of an 
     authenticated user. This is done by verifying that user token provided 
     as the Authorization header is valid by calling the auth API.

     Here, we can ${ConfirmThat().authLambdaWasCalled} by the handler
   """

 case class ConfirmThat() {
   def interactions = mock[Interactions]

  def authLambdaWasCalled = {
    val reqHandler = Request[Input](
       headers = Map[String, String](
          "Authorization" -> "Bearer gagagaga"
       )
      // millions of values that are not directly related
    )
    MyHandler.handler(reqHandler, null)
    there was one(interactions).authenticateUser(Some("gagagaga"))
  }
 }
}

代码

代码使用类 MyHandler 扩展了 trait Interactions:

 trait Interactions extends MyServiceTrait with AuthServiceTrait {
    def authenticateUser(token: Option[String]): Future[Either[Errors, Boolean]] = {
  Future.successful(Right(true))
 }
}

class MyHandler extends Interactions with Utils {

  override def handler(request: Request[Input], c: Context): Response[Errors, Output] = { 
    //  get the auth token from the headers as an option, 
    //  there is a method in Utils that I unit tested
    //  it been omitted here for clarity

    val authFuture = authenticateUser(bearerToken)
  }  
}

错误

当我运行代码时,我看到以下错误:

The mock was not called as expected: 
[error]  Wanted but not invoked:
[error]  interactions.authenticateUser(
[error]      Some(gagagaga)
[error]  );
[error]  -> at com.lendi.lambda.MyHandlerSpec$ConfirmThat.$anonfun$authLambdaWasCalled$1(MyHandlerSpec.scala:71)
[error]  Actually, there were zero interactions with this mock. (MyHandlerSpec.scala:71)

我如何确保我可以:

a) 将用于身份验证的代码移动到 MyHandler 中,并使用 specs2 提供的 Mockito 对 MyHandler 进行部分模拟

b) 确保我模拟了交互并将交互注入代码中,以便处理程序可以正确地模拟它。

c) 使用 DI 框架(我应该为我的 lambda 使用 Spring)来注入交互并使用 DI 框架模拟它。

【问题讨论】:

  • 我缺少MyHandler.handler 的代码。它有什么作用?似乎也没有什么实际调用interactions。我怀疑您实际上需要在MyHandler 中使用interactions,方法是将其作为构造函数参数传递,而不是扩展特征。然后你将能够传递一个将在测试期间调用的模拟。
  • @Eric authenticateUser 作为中间步骤在处理程序内部被调用。为不完整的代码道歉,已修复它并更改了某些消息。
  • 问题依旧。您正在从与 MyHandler 混合的特征中调用 authenticateUser,而不是从您在 ConfirmThat 中构建的模拟对象中调用。

标签: scala mocking mockito aws-lambda specs2


【解决方案1】:

你需要将你的模拟对象传递给MyHandler

class MyHandler(interactions: Interactions) with Utils

然后

val interactions = mock[Interactions]
val myHandler = MyHandler(interactions)

MyHandler.handler(reqHandler, null)

【讨论】:

  • 谢谢,会在接受答案之前尝试一下,我有一个问题,我无法实例化MyHandler 并自己调用handler 方法。这需要由 AWS 作为 lambda 执行。这在那种情况下会起作用吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-21
  • 1970-01-01
  • 2016-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
相关资源
最近更新 更多