[Scala][Mokito] 如何存根 Future 函数以抛出异常
[Scala][Mokito] How to stub a Future function to throw exception
我正在编写存根存储库的测试用例 Future
函数抛出一个 Exception
来模拟一些数据库错误。
我希望 Repository.create 抛出数据库异常,它将由 Actor .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
}
}
这是输出:
[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
我曾尝试用 thenThrow(new Exception)
替换 thenReturn(Future.failed..
但无法正常工作,出现错误 ava.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg while waiting for
您不想抛出 Future.failed
中的异常,只需在那里创建它。在对真实存储库的调用中发生的事情是在 Future
结果的 计算 中抛出异常,然后将捕获并放置在 Failure
实例,而不是将成功的计算结果放在 Success
实例中。所以:
when(repository.create(any[Team])(same(ec))).thenReturn(Future.failed(new Exception(...)))
应该完成这项工作。
我正在编写存根存储库的测试用例 Future
函数抛出一个 Exception
来模拟一些数据库错误。
我希望 Repository.create 抛出数据库异常,它将由 Actor .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
}
}
这是输出:
[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
我曾尝试用 thenThrow(new Exception)
替换 thenReturn(Future.failed..
但无法正常工作,出现错误 ava.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg while waiting for
您不想抛出 Future.failed
中的异常,只需在那里创建它。在对真实存储库的调用中发生的事情是在 Future
结果的 计算 中抛出异常,然后将捕获并放置在 Failure
实例,而不是将成功的计算结果放在 Success
实例中。所以:
when(repository.create(any[Team])(same(ec))).thenReturn(Future.failed(new Exception(...)))
应该完成这项工作。