【问题标题】:Scala avoid Thread sleep for asynchronous test casesScala 避免异步测试用例的线程休眠
【发布时间】:2020-06-19 11:32:18
【问题描述】:

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

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 的期望。

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

【问题讨论】:

  • 你用的是什么测试库?

标签: multithreading scala testing future


【解决方案1】:

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

虽然期货被定义为一种只读占位符对象 为尚不存在的结果创建,可以认为是一个承诺 of 作为一个可写的、单一赋值的容器,它完成了一个 未来。也就是说,一个promise可以用来成功完成一个 未来的价值(通过“完成”承诺)使用成功 方法。相反,一个promise也可以用来完成一个future 有一个例外,通过失败的承诺,使用失败的方法。

promise p 完成了 p.future 返回的未来。这个未来是 特定于承诺 p。根据实现,它可能是 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,如下所示: promise completeWith f1 然后,使用promiseFuture onComplete 添加一个处理程序,当它成功或失败时要做什么。

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

告诉我它有帮助!

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 2012-11-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多