With livestub you can easly setup http server that behaves exactly as you would like it to. That makes livestub a perfect solution for faking arbitrary services which might be very useful in development/testing.
-
coursier
coursier launch com.softwaremill.sttp.livestub:livestub-app_2.13:0.2.1 -- -p 7070
-
docker
docker run -p 7070:7070 softwaremill/sttp.livestub
-
code
import sttp.livestub.app.LiveStubServer
import sttp.livestub.app.LiveStubServer.Config
LiveStubServer.resource(Config(port = 7070))
curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"GET", "url":"animals/1/status"}, "then": {"statusCode":200, "body":{"status": "happy"} }}'
curl 'localhost:7070/animals/1/status'
{"status":"happy"}
Swagger is available under /__admin/docs
Livestub supports wildcard http methods as well as wildcard path parameters.
wildcard method:
curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"*", "url":"dogs"}, "then": {"statusCode":200, "body":{"status": "OK"} }}'
wildcard path param:
curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"GET", "url":"dogs/*/status"}, "then": {"statusCode":200, "body":{"status": "happy"} }}'
multiwildcard path param: (this one catches all routes which originate from /dogs
)
curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"GET", "url":"dogs/**"}, "then": {"statusCode":200, "body":{"status": "cheerful"} }}'
wildcard query param: (this one catches all the query parameters for /dogs
, example: /dogs?id=1&breed=bulldog
)
curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"GET", "url":"dogs?*"}, "then": {"statusCode":200, "body":{"status": "cheerful"} }}'
clear stubbed routes
curl -X POST 'localhost:7070/__clear'
show stubbed routes
curl 'localhost:7070/__routes'
set many responses which will be cycled through
curl -X POST 'localhost:7070/__set_many' \
-d '{"when":{"method":"GET", "url":"animals/1/status"}, "then": [
{"statusCode":200, "body":{"status": "happy"} },
{"statusCode":200, "body":{"status": "unhappy"} }
]
}'
libraryDependencies += "com.softwaremill.sttp.livestub" % "livestub-sdk" % "0.2.1"
Given a bunch of imports
import sttp.client3.asynchttpclient.cats.AsyncHttpClientCatsBackend
import sttp.client3.SttpBackend
import sttp.livestub.sdk._
import sttp.livestub.api._
import sttp.client3.{Response => _, _}
import sttp.model._
import io.circe.Json
you can stub an arbitrary request:
AsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =>
val livestub = new LiveStubSdk[IO](uri"http://mock:7070", backend)
livestub
.when(RequestStubIn(MethodStub.Wildcard, "/user/*/status"))
.thenRespond(Response.emptyBody(StatusCode.Ok, List(Header("X-App", "123"))))
}
stub given sttp request:
AsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =>
val request = basicRequest
.body(Map("name" -> "John", "surname" -> "doe"))
.post(uri"https://httpbin.org/post?signup=123")
val livestub = new LiveStubSdk[IO](uri"http://mock:7070", backend)
livestub.when(request).thenRespond(Response(Some(Json.fromString("OK")), StatusCode.Ok))
}
or stub given tapir endpoint:
import sttp.tapir._
AsyncHttpClientCatsBackend[IO]().flatMap { backend: SttpBackend[IO, Any] =>
val myEndpoint = endpoint.get.in("/status").out(stringBody)
val livestub = new LiveStubSdk[IO](uri"http://mock:7070", backend)
livestub.when(myEndpoint)
.thenRespond(Response.emptyBody(StatusCode.Ok, List(Header("X-App", "123"))))
}
OpenApi specification can be provided to bootstrap livestub server with auto generated endpoints. For each given path a request-response stub will be generated matching particular url. Both path parameters and required query parameters will be replaced by wildcard matches. That means that neither optional query parameters, request body nor headers are going to be checked when matching stubbed endpoint.
Response structure will follow openapi schema. Response data will be created based on openapi respective example parameters if provided, otherwise random data will be used(whenever it is possible).
For endpoints, which are defined in openapi specification but for which responses couldn't be generated empty response body will be returned.
Usage:
--openapi-spec <path_to_file>
In addition, seed value for random data generator can be passed via:
--seed 1234
Documentation is generated during every release from docs-sources
directory.
It can be manually regenerated when needed by calling sbt docs/mdoc
.
To release new version use sbt release
.