简体   繁体   English

[Scala] [Mokito]如何将Future函数存根以引发异常

[英][Scala][Mokito] How to stub a Future function to throw exception

I m writing test case for stubbing a repository Future function throws an Exception to simulate some DB error. 我正在编写用于对存储库进行存根的测试用例, Future函数将引发Exception以模拟某些DB错误。

I expect the DB exception throw by Repository.create and it will be handled by Actor .recover{} . 我期望Repository.create抛出数据库异常,它将由Actor .recover{}处理。 But it throws an exception and cannot be caught by .recover 但这会引发异常,并且无法被.recover捕获

// test 
it should "return NOT created message if exception thrown" in {
    val repository = mock[Repository]
    val service = TestActorRef(props(repository))
    implicit val ec: ExecutionContext = service.dispatcher
    val mockTeam = mock[Team]

    when(repository.create(any[Team])(same(ec))).thenReturn(Future.failed(throw new Exception))
    service ! CreateTeam(mockTeam)
    expectMsg(TeamNotCreated())
}


// service == actor
override def receive = {
    case CreateTeam(team) => createTeam(team)
    .recover {
      case error: Exception => TeamNotCreated()
    }.pipeTo(sender())
}
private def createTeam(team: Team)
  : Future[TeamCreateEvent] = {
        for {
          newTeam <- repository.create(team = team)
        } yield {
          if (newTeam isDefined) TeamCreated(newTeam)
          else TeamNotCreated()
        }
      }

// repository
override def create(team: TeamEntity)(implicit ec: ExecutionContext)
  : Future[Option[TeamEntity]] = {
    Future {
      val column = Team.column
      /****  I want to simulate some exception was thrown here ***/
      val newId = Team.createWithNamedValues(
        column.name -> team.name
      )
      if (newId.isValidLong) Option(team.copy(id = newId)) else None
    }
  }

Here is the output: 这是输出:

[info] - should return NOT created message if exception thrown *** FAILED ***
[info]   java.lang.Exception:
 should return updated message if collaborator team create success *** FAILED ***
[info]   org.mockito.exceptions.misusing.UnfinishedStubbingException: 

Unfinished stubbing detected here:
.g. thenReturn() may be missing.
[info] Examples of correct stubbing:
[info]     when(mock.isOk()).thenReturn(true);
[info]     when(mock.isOk()).thenThrow(exception);
[info]     doThrow(exception).when(mock).someVoidMethod();
[info] Hints:
[info]  1. missing thenReturn()
[info]  2. you are trying to stub a final method, you naughty developer!
[info]  3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

I had tried to to replace thenReturn(Future.failed.. with thenThrow(new Exception) but not working with error ava.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg while waiting for 我试图用thenThrow(new Exception)替换thenReturn(Future.failed.. thenThrow(new Exception)但无法处理错误ava.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg while waiting for

You don't want to throw the Exception inside the Future.failed , just create it there. 您不想将Exception 抛出Future.failed内部,只需在其中创建它即可。 What happens in a call to a real repository is that an Exception is thrown in the calculation of the Future 's result, and this would then be caught and placed in a Failure instance, rather than a successful calculation result being placed in a Success instance. 调用真实存储库时发生的情况是,在计算 Future的结果时引发了异常,然后将其捕获并放置在Failure实例中,而不是将成功的计算结果放置在Success实例中。 So: 所以:

when(repository.create(any[Team])(same(ec))).thenReturn(Future.failed(new Exception(...)))

should do the job. 应该做的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM