livestub

Build Status Docker Pulls ImageLayers Scala Steward badge Maven Central

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.

Usage

launch

  • coursier

    coursier launch com.softwaremill.sttp.livestub:livestub-app_2.13:0.1.10 -- -p 7070

  • docker

    docker run -p 7070:7070 softwaremill/sttp.livestub

stub

curl -X POST 'localhost:7070/__set' \
-d '{"when":{"method":"GET", "url":"animals/1/status"}, "then": {"statusCode":200, "body":{"status": "happy"} }}'

invoke

curl 'localhost:7070/animals/1/status'
{"status":"happy"}

swagger

Swagger is available under /__admin/docs

advanced stubbing

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"} }}'

additional methods

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"} }
  ]
}'

stubbing from code - sdk

libraryDependencies += "com.softwaremill.sttp.livestub" % "livestub-sdk" % "0.1.10"

Given that very self-explanatory bootstrap:

import cats.effect._
import sttp.client.asynchttpclient.cats.AsyncHttpClientCatsBackend
import sttp.client.asynchttpclient._
import sttp.client.SttpBackend
import scala.concurrent._
import sttp.livestub.sdk._
import sttp.livestub.api._
import sttp.client.{Response => _, _}
import sttp.model._
import io.circe.Json

implicit val cs = IO.contextShift(ExecutionContext.global)
implicit val timer = IO.timer(ExecutionContext.global)

you can stub an arbitrary request:

AsyncHttpClientCatsBackend[IO]().flatMap { implicit backend: SttpBackend[IO, Nothing, WebSocketHandler] =>
  val livestub = new LiveStubSdk[IO, Nothing, WebSocketHandler](uri"http://mock:7070")
  livestub
    .when(RequestStub(MethodValue.Wildcard, "/user/*/status"))
    .thenRespond(Response.emptyBody(StatusCode.Ok, List(Header("X-App", "123"))))
}

stub given sttp request:

AsyncHttpClientCatsBackend[IO]().flatMap { implicit backend: SttpBackend[IO, Nothing, WebSocketHandler] =>
  val request = basicRequest
    .body(Map("name" -> "John", "surname" -> "doe"))
    .post(uri"https://httpbin.org/post?signup=123")

  val livestub = new LiveStubSdk[IO, Nothing, WebSocketHandler](uri"http://mock:7070")
  livestub.when(request).thenRespond(Response(Some(Json.fromString("OK")), StatusCode.Ok))
}

or stub given tapir endpoint:

import sttp.tapir._

AsyncHttpClientCatsBackend[IO]().flatMap { implicit backend: SttpBackend[IO, Nothing, WebSocketHandler] =>
  val myEndpoint = endpoint.get.in("/status").out(stringBody)

  val livestub = new LiveStubSdk[IO, Nothing, WebSocketHandler](uri"http://mock:7070")
  livestub.when(myEndpoint)
          .thenRespond(Response.emptyBody(StatusCode.Ok, List(Header("X-App", "123"))))
}