ScalaTest使用AsyncFunSuiteLike声明多个期货

时间:2018-10-05 18:25:29

标签: scala scalatest

我一直在尝试执行一个测试,该测试使用模拟Http服务器进行响应,并且如果Http服务器响应不是200,则该函数返回Future [String]或Exception。

我正在尝试不使用Awaits而是通过AsyncFunSuiteLike来实现测试。

但是,如果不同步执行以下测试,似乎无法解决:

test("Error responses") {
    Future.sequence {
      NanoHTTPD.Response.Status.values().toList.filter(status => status.getRequestStatus >= 400).map {
        status => {

          httpService.setStatusCode(status)
          val responseBody = s"Request failed with status $status"
          httpService.setResponseContent(responseBody)
          val errorMessage = s"Error response (${status.getRequestStatus}) from http service: $responseBody"

          recoverToExceptionIf[ServiceException] {
            myObject.httpCall("123456")
          }.map {
            ex => assert(ex.getMessage === errorMessage)
          }
        }
      }
    }.map(assertions => assert(assertions.forall(_ == Succeeded)))
}

基本上的问题是,在测试期货时,NanoHTTPD设置为映射中的最后一个值集,因此所有ex.getMessage都相同。如果我一一运行这些状态代码,就可以得到预期的结果,但是,有没有一种方法可以在一个异步测试中执行所有这些操作呢?

1 个答案:

答案 0 :(得分:0)

从外观上看,NanoHTTPD是有状态的,因此您需要在.set...调用和.httpCall之间进行竞争。

如果您可以在每个Future中旋转一个新的httpService,那么您应该能够并行化测试(除非所讨论的状态可以在实例之间共享,在这种情况下,您可能会走运)。

因此,您会遇到类似的事情(在代码中将Status替换为status,将HTTPService替换为httpService):

// following code composed on the fly and not run through the compiler...
def spinUpHTTPService(status: Status, body: String): Future[HTTPService] = {
  // insert the code outside of the test which creates httpService

  httpService.setStatusCode(status)
  httpService.setResponseContent(body)

  httpService
}

test("Error responses") {
  Future.sequence(
    NanoHTTPD.Response.Status.values().toList.filter(status => status.getRequestStatus >= 400).map { status =>
      spinUpHTTPService(status, s"Request failed with status $status")
        .flatMap { httpService =>
          val errorMessage = s"Error response (${status.getRequestStatus}) from http service: $responseBody"

          recoverToExceptionIf[ServiceException] {
            myObject.httpCall("123456")
          } map {
            ex => assert(ex.getMessage === errorMessage)
          }
        } // Future.flatMap
    }  // List.map
  ).map { assertions => assertions.forAll(_ == Succeeded) }
}