multithreading - Scala 避免异步测试用例的线程休眠

标签 multithreading scala testing future

我正在为运行主要功能然后异步记录有关请求的详细信息的方法编写单元测试。

def someMethod(data: Object): SomeType =
  for {
    result <- someOtherMethod(data).withLogging(logMethod)
  }

logMethod 方法是一个异步任务。在我的测试中,我想确保记录器正在接收一条消息,但是,线程有时会完成得太快,从而使测试不稳定,有时会导致 Unsatisfied 结果。

示例测试用例:

it("logs an error if an upload was attempted with some failure case") {
  val uploadData = someData

  mockSomeCall()

  mockAnotherCall()

  testController.methodWeAreTesting(uploadData).shouldBeRight()

  Thread.sleep(75)

  (stubLogger
    .warn(_: RichMsg, _: Throwable, _: AnyId)(_: () => SourceLocation))
    .verify(where { (msg: RichMsg, _, _, _) =>
      msg.toString.equals(s"Some specific message")
     })
}

每次我需要确保记录器接收到特定消息时,我都不喜欢添加 Thread.sleep。我希望能够包装 stubLogger 期望。

如果需要更多信息,请告诉我。

最佳答案

我认为 promise 是您需要在 logMethod 中添加的内容。 根据 documentation :

While futures are defined as a type of read-only placeholder object created for a result which doesn’t yet exist, a promise can be thought of as a writable, single-assignment container, which completes a future. That is, a promise can be used to successfully complete a future with a value (by “completing” the promise) using the success method. Conversely, a promise can also be used to complete a future with an exception, by failing the promise, using the failure method.

A promise p completes the future returned by p.future. This future is specific to the promise p. Depending on the implementation, it may be the case that p.future eq p.

在测试中,一旦得到结果,就可以将结果与您尝试比较的消息进行比较。

示例代码如下:

object Test1 extends App {
  import scala.concurrent.{Future, Promise}
  import scala.concurrent.ExecutionContext.Implicits.global
  import scala.util.{Success, Failure}

  var promiseMessage: String = _
  val promise = Promise[String] //The promise will hold a string

  //A future tells the System to spawn a new thread and run the code block inside it
  val logMethod =  (elem: String) => Future{
    promise.success(elem)
    elem
  }

  def method(data: String): Future[String] = {
    for {
      result <- logMethod(data)
    } yield result
  }

  val f1 = method("Hi!! I love scala async programming")

  promise completeWith f1
  val promiseFuture = promise.future

  promiseFuture onComplete {
    case Success(value) =>
      promiseMessage = value
      println(promiseMessage)
    case Failure(ex) => println(ex)
  }

  Await.result(promiseFuture, 100 seconds)

  if (promiseMessage == "Hi!! I love scala async programming") println("correct")
}

在代码中,promise 是一个 Promise 对象,它在 future 完成时 promise 一个字符串。您需要做的就是用 future 完成 promise ,如下所示: promise completeWith f1 然后,使用 promiseFuture onComplete 添加一个处理程序,说明在成功或失败时要做什么。

如果你想检查日志记录是否发生,你可以在 promiseFutureawait 或者继续进一步的过程,当日志记录完成时,promise 将打印成功如代码所示。

让我知道它有帮助!!

关于multithreading - Scala 避免异步测试用例的线程休眠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60569006/

相关文章:

scala - 在 Scala 中填充所需的行

spring - 我应该在 Spring 项目中包含系统测试吗?

ios - 当模式对话框显示时,GREYAction 不起作用

c# - 发送 Exchange WS 电子邮件 - 线程池中没有足够的可用线程来完成操作

c - 调用 pthread_exit() 时发生内存泄漏

Java无限线程在一段时间后停止

ios - ECSlidingViewController 和测试

java - sleep 线程唤醒后会发生什么?

scala - Spark MergeSchema 在 Parquet 列上

scala - Scala试试,其他,除 block