我一直在尝试执行一个测试,该测试使用模拟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
都相同。如果我一一运行这些状态代码,就可以得到预期的结果,但是,有没有一种方法可以在一个异步测试中执行所有这些操作呢?
答案 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) }
}