这是正在测试的代码:
import concurrent.{ExecutionContext, Future}
trait Backend {
def verifyUser(): Future[Unit]
def accounts(): Future[String]
}
class Service(backend: Backend) {
private implicit val executor: ExecutionContext = ExecutionContext.global
def accounts(): Future[String] =
(for (_ <- backend.verifyUser(); accs <- backend.accounts()) yield accs)
.recover { case ex => s"failed: ${ex.getMessage}" }
}
和测试
import org.scalatest._
import matchers.should
import flatspec.AsyncFlatSpec
import org.mockito.scalatest.AsyncIdiomaticMockito
class ServiceTest extends AsyncFlatSpec with AsyncIdiomaticMockito with should.Matchers {
private trait Fixture {
lazy val backend: Backend = mock[Backend]
lazy val service: Service = new Service(backend)
}
it should "return the reason of a failure" in {
val fixture = new Fixture {}
import fixture._
val backend = mock[Backend]
val service = new Service(backend)
backend.verifyUser() returns Future.failed(new RuntimeException("verifyUser"))
backend.accounts() returns Future.failed(new RuntimeException("accounts"))
service.accounts() map { result =>
result should startWith ("failed: ")
}
}
}
结果是
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
1. -> at ServiceTest.$anonfun$new$1(StrictStubbingTest.scala:25)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
org.mockito.exceptions.misusing.UnnecessaryStubbingException:
如何在保留两个存根的情况下使测试正常工作?如何按照建议仅针对该测试用例而不是针对整个测试类启用“宽松”严格性?
我的小伙伴给出了这样的解决方案:
class ServiceTest extends AsyncFlatSpec with AsyncIdiomaticMockito with should.Matchers {
private trait Fixture {
lazy val backend: Backend = mock[Backend]
lazy val service: Service = new Service(backend)
}
it should "return the reason of a failure" in {
val fixture = new Fixture {
override lazy val backend: Backend = mock[Backend](withSettings.lenient())
}
import fixture._
backend.verifyUser() returns Future.failed(new RuntimeException("verifyUser"))
backend.accounts() returns Future.failed(new RuntimeException("accounts"))
service.accounts() map { result =>
result should startWith ("failed: ")
}
}
}
那就是对Backend进行宽松的嘲笑。