Мы делаем это так, как вы называете dirty
, хотя я не думаю, что это dirty
.
у нас есть базовая черта, которая запускает / выключает сервер (мы используем http4s и scalatest)
trait EmbeddedServer extends BeforeAndAfterAll with Http4sDsl[IO] {
self: Suite =>
private var server: Server[IO] = _
protected var lastRequest: Request[IO] = _
private def captureRequest: HttpService[IO] = Kleisli { req: Request[IO] =>
lastRequest = req
service(req)
}
override protected def beforeAll(): Unit = {
server = BlazeBuilder[IO]
.bindAny()
.mountService(captureRequest, "/")
.start
.unsafeRunSync()
super.beforeAll()
}
override protected def afterAll(): Unit = {
super.afterAll()
server.shutdownNow()
}
def address: InetSocketAddress = server.address
def rootURI: String = s"http:/$address"
def service: HttpService[IO]
}
тогда мы смешиваем это в нашей client
спецификации
что-то в этом роде
class SomeRequesterSpec extends WordSpec with EmbeddedServer {
override def service: HttpService[IO] = HttpService[IO] {
case GET -> Root / "failure" => ServiceUnavailable()
case GET -> Root / "success" => Ok(SuccessBody)
case GET -> Root / "partial-success" => Ok(PartialSuccessBody)
case GET -> Root / "malformed" => Ok(MalformedBody)
case GET -> Root / "empty" => Ok(EmptyResponse)
}
//... you specs go here
}
и в своих спецификациях вы звоните на сервер mocked
со своим клиентом
используя s"$rootURI/success"
или s"$rootURI/failure"
конечные точки и проверьте, правильно ли он обрабатывает ответы.
Также lastRequest
var всегда имеет проблемы с последним запросом, так что вы можете запускать утверждения против него, как
lastRequest.headers should contain(`Accept-Encoding`(ContentCoding.gzip))
Этот подход очень хорошо работает для нас, и мы можем проверить, что наши клиенты обрабатывают все виды выходных данных с серверов, а также все манипуляции с запросом, который они делают