只在specs2单元测试(Scala)中面对一些奇怪的强制转换异常



我有一个服务方法如下:

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)

我甚至不知道从哪里开始。

在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测试中使用mock。使用特征和最小实现将让编译器指出这些错误。mock将这些检查移到运行时并混淆实际原因,就像在这个例子中一样。

最新更新