我有一个服务方法如下:
override def update(group: JourneyGroup, name: String, operator: User): Future[Either[String, JourneyGroup]] = {
for {
updatedCount <- journeyGroupDao.update(group.copy(name = name), operator.id.get)
updatedGroup <- journeyGroupDao.findOneById(group.id.get)
} yield
(updatedCount, updatedGroup) match {
case (1, Some(g)) =>
system.eventStream.publish(JourneyGroupUpdated(g, group))
Right(g)
case (1, None) => Left(s"failed to find updated journey group object - ${group.id.get}")
case _ => Left(s"failed to update journey group object - ${group.id.get}")
}
}
它的单元测试看起来像这样:
val existingGroup = mock[JourneyGroup]
existingGroup.id returns Some(123)
val updatedGroup = mock[JourneyGroup]
val operator = mock[User]
operator.id returns Some(876)
doReturn(Future.successful(1)).when(journeyGroupDao).update(Matchers.any[JourneyGroup], Matchers.eq(876))
doReturn(Future.successful(updatedGroup)).when(journeyGroupDao).findOneById(123, includeDeleted = false)
doNothing.when(eventStream).publish(Matchers.any[JourneyGroupUpdated])
val future = journeyGroupService.update(existingGroup, "new name", operator)
Await.result(future, Duration.Inf) must beRight{ g: JourneyGroup =>
g must_=== updatedGroup
}
there was one(eventStream).publish(Matchers.any[JourneyGroupUpdated])
该方法在常规执行中完美运行。但是,当我运行测试时,我得到了投射错误:
[error] java.lang.ClassCastException: model.JourneyGroup$$EnhancerByMockitoWithCGLIB$$a9b16db0 cannot be cast to scala.Option (JourneyGroupService.scala:101)
[error] services.JourneyGroupServiceImpl$$anonfun$update$1$$anonfun$apply$1.apply(JourneyGroupService.scala:101)
我甚至不确定从哪里开始。我很感激任何想法。
答案 0 :(得分:2)
在for-comprehension的代码中说返回类型为:
updatedGroup <- journeyGroupDao.findOneById(group.id.get)
是Option[JourneyGroup]
,但在模拟互动的声明中,会给出JourneyGroup
:
val updatedGroup = mock[JourneyGroup]
...
doReturn(Future.successful(updatedGroup)).when(journeyGroupDao).findOneById(123, includeDeleted = false)
updatedGroup
必须是Option[JourneyGroup]
那就是说,我不建议在Scala测试中使用模拟。使用traits和最小化实现将让编译器指出这些错误。模拟将这些检查移动到运行时并模糊了实际原因,就像在这种情况下一样。