scala - 在 Mockito 单元测试中抛出异常时,Future 的 .recover 不会被调用

标签 scala mockito scalatest

以下代码返回一个 Future。

val findUserFuture: Future[Option[User]] = userRepo.findOne(userKeys) 

然后我处理 future
findUserFuture.flatMap {....}
.recover{...}
fineOne返回 FutureFuture结束对 getOneById 的调用
def findOne(userKeys:UserKeys):Future[Option[User]] = {
    Future{
      //val loginInfo:LoginInfo = LoginInfo(userKeys.providerID,userKeys.authProvider)
      val userOption:Option[User] = getOneById(userKeys)
      userOption
    }
  }

我想如果 Future 会调用recover返回者 findOne失败,即抛出异常。所以我通过制作 getOneById 来模拟这一点抛出异常。
when(mockUserRepository.findOne(userKeys)).thenReturn(Future(Some(user)))
      when(mockUserRepository.getOneById(userKeys)).thenThrow(classOf[RuntimeException]) //simulating database error

但单元测试不会抛出异常,测试继续使用值 Future(Some(User)) .

我也尝试从 findOne 抛出异常- when(mockUserRepository.findOne(userKeys)).thenThrow(classOf[RuntimeException])但是测试用例停止了
带有以下两个打印件和 .recoverFuture不叫
java.lang.RuntimeException was thrown.
java.lang.RuntimeException

最佳答案

findUserFuture: Future[Option[User]]userRepo.findOne返回 future ,
因此您需要返回 Future.failed在你的模拟中。
例如。

when(mockUserRepository.findOne(userKeys)).thenReturn(Future(Some(user)))
when(mockUserRepository.getOneById(userKeys)).thenReturn(Future.failed(new RuntimeException("network failure"))

在下面找到完整的工作测试来模拟您的用例:
test("mock future test") {
    case class User(name: String)
    case class UserNotFoundException(name: String) extends Exception
    trait UserRepo {
      def findOne(name: String): Future[Option[User]]
    }
    val name      = "bob"
    val dummyUser = User("dummy")

    val userRepo = mock[UserRepo]
    when(userRepo.findOne(name)).thenReturn(Future.failed(new RuntimeException()))

    val userF = userRepo
      .findOne(name)
      .flatMap {
        case Some(user) ⇒ Future.successful(user)
        case None       ⇒ Future.failed(UserNotFoundException(name))
      }
      .recover {
        case NonFatal(_) ⇒ dummyUser
      }

    userF.futureValue shouldBe dummyUser
  }
  • 更新 *
    在仔细查看原始帖子后,我发现您 mock 的方式存在小错误。
    试试以下:
  • when(mockUserRepository.findOne(userKeys)).thenCallRealMethod()
    when(mockUserRepository.getOneById(userKeys)).thenThrow(classOf[RuntimeException]) 
    

    通知thenCallRealMethod()在这里,早些时候你在 mock findOne以成功的值返回 future ,这意味着原始方法没有被调用,而原始方法没有被调用 getOneById

    关于scala - 在 Mockito 单元测试中抛出异常时,Future 的 .recover 不会被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55135244/

    相关文章:

    java - 在对 void 方法进行单元测试时,如何确定集合中的元素?

    Scalatest:WAITING断言变为真

    java - 将 Scalatest 包含在 Java 中时 Maven 构建失败

    scala - 在 Scaladoc 中,如何链接到同一类中的方法?

    scala - 如何在 SBT 多项目中共享自定义任务

    scala - 从 Play 2.0 Scala Controller 中的请求获取表单参数值

    java - 为什么 Mockito.when(...).thenThrow(...) 直接抛出错误

    scala - 通过索引选择 TreeMap 的键

    java - Mockito 相当于 EasyMock 的 MockBuilder

    scala - 使用 MockFactory 模拟配置对象