C0d*_*ack 12 testing unit-testing scala scalatest spray
当涉及隐式参数时,我在尝试理解如何在Scala中编写测试时遇到了一些困难.
我有以下(简短版本)我的代码和测试:
实施(Scala 2.10,Spray和Akka):
import spray.httpx.SprayJsonSupport._
import com.acme.ResultJsonFormat._
case class PerRequestIndexingActor(ctx: RequestContext) extends Actor with ActorLogging {
def receive = LoggingReceive {
case AddToIndexRequestCompleted(result) =>
ctx.complete(result)
context.stop(self)
}
}
object ResultJsonFormat extends DefaultJsonProtocol {
implicit val resultFormat = jsonFormat2(Result)
}
case class Result(code: Int, message: String)
Run Code Online (Sandbox Code Playgroud)
测试(使用ScalaTest和Mockito):
"Per Request Indexing Actor" should {
"send the HTTP Response when AddToIndexRequestCompleted message is received" in {
val request = mock[RequestContext]
val result = mock[Result]
val perRequestIndexingActor = TestActorRef(Props(new PerRequestIndexingActor(request)))
perRequestIndexingActor ! AddToIndexRequestCompleted(result)
verify(request).complete(result)
}
}
Run Code Online (Sandbox Code Playgroud)
这一行verify(request).complete(result)使用隐式Marshaller转换Result为JSON.
我可以通过添加将一个编组器带入范围,implicit val marshaller: Marshaller[Result] = mock[Marshaller[Result]]但是当我运行测试时,使用了不同的Marshaller实例,因此验证失败.
甚至明确地将模拟Marshaller传递给complete失败.
那么,任何人都可以建议如何为隐式参数创建一个模拟对象,并确保该实例是使用的实例?
这是一个完美的情况,使用MatcherMockito为marshaller arg.你不应该嘲笑隐式编组.你真正想做的就是验证你complete所调用的result匹配你所期望的以及marshaller的一些实例.首先,如果您还没有这样做,请将Mockito匹配器带入范围,并使用如下导入:
import org.mockito.Matchers._
Run Code Online (Sandbox Code Playgroud)
然后,如果你想在结果上进行参考匹配,你可以这样验证:
verify(request).complete(same(result))(any[classOf[Marshaller[Result]]])
Run Code Online (Sandbox Code Playgroud)
或者,如果你想在结果上匹配等于你可以做到:
verify(request).complete(eq(result))(any(classOf[Marshaller[Result]]))
Run Code Online (Sandbox Code Playgroud)
匹配器的技巧是,一旦你使用一个arg,你必须使用它们为所有args,所以这就是为什么我们也必须使用它result.