Scala避免异步测试案例的线程休眠

问题描述 投票:2回答:1

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

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个回答
0
投票

我认为您需要在promise中添加logMethod。按照documentation

虽然期货被定义为一种只读占位符对象 为尚不存在的结果而创建,可以考虑一个承诺 作为一个可写的单任务容器,它完成了 未来。也就是说,可以使用诺言来成功完成 拥有成功的价值(通过“完成”承诺)的未来 方法。相反,承诺也可以用来完成未来 例外情况是,通过使用失败方法,未能履行承诺。

承诺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对象,当将来完成时,它会承诺一个字符串。您需要做的就是完成对未来的承诺,如下所示:promise completeWith f1,然后使用promiseFuture onComplete添加有关成功或失败时的处理程序。

如果要检查是否已发生日志记录,可以在await上单击promiseFuture或继续进行进一步的过程,并且在完成日志记录后,将如代码中所示成功地打印出Promise。

让我知道它会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.