0

我正在为我的代码的一些异步部分(返回Futures)编写单元测试,这也涉及到模拟 Scala 对象的需要。按照这些文档,我可以成功地模拟对象的功能。我的问题源于return ,其中 scalatest 中的异步测试需要withObjectMocked[FooObject.type]返回or 。为了解决这个问题,我在我的测试中创建了 s,我在发送到的函数中重新分配,最终看起来像这样:UnitAssertionFuture[Assertion]varwithObjectMocked[FooObject.type]

class SomeTest extends AsyncWordSpec with Matchers with AsyncMockitoSugar with ResetMocksAfterEachAsyncTest {
      "wish i didn't need a temp var" in {
        var ret: Future[Assertion] = Future.failed(new Exception("this should be something")) // <-- note the need to create the temp var

        withObjectMocked[SomeObject.type] {
          when(SomeObject.someFunction(any)) thenReturn Left(Error("not found"))

          val mockDependency = mock[SomeDependency]
          val testClass = ClassBeingTested(mockDependency)

          ret = testClass.giveMeAFuture("test_id") map { r =>
              r should equal(Error("not found"))
          } // <-- set the real Future[Assertion] value here
        }

        ret // <-- finally, explicitly return the Future
      }
}

那么我的问题是,是否有更好/更干净/更惯用的方法来编写模拟对象的异步测试,而无需跳过这一圈?出于某种原因,我认为使用AsyncMockitoSugar而不是MockitoSugar会为我解决这个问题,但withObjectMocked仍然返回Unit。这可能是一个错误和/或功能请求的候选者(withObjectMocked返回功能块值的异步版本,而不是Unit)?还是我错过了如何完成此类任务?

4

1 回答 1

1

您应该避免mockObject在多线程环境中使用,因为它不能很好地使用它。这是因为object代码存储为单例实例,因此它实际上是全局的。

当您使用时,mockObject您将有效地强制覆盖它var(代码负责恢复原始代码,因此如果您愿意,可以将其用作“资源”的语法)。

因为这var是全局/共享的,所以如果您进行多线程测试,最终会出现随机行为,这就是不提供异步 API 的主要原因。

无论如何,这是一个不得已的工具,每次你发现自己使用它时,你应该先停下来问问自己你的代码是否有任何问题,这里有很多模式可以帮助你(比如注入依赖项),因此您应该很少需要这样做。

于 2021-10-20T14:48:20.863 回答