Reputation: 141
i cant find anywere how to make a stub of IO tapir endpoint. In the docs https://tapir.softwaremill.com/en/latest/testing.html i can see only example for scala Future.
Basically i need to make a stub for tapir endpoint
endpoint
.post
.in("v1" / "payment")
.securityIn(auth.basic[UsernamePassword]())
.in(jsonBody[HttpPaymentRequest])
.out(jsonBody[HttpPaymentResponse])
.errorOut(oneOf[StatusError](
oneOfVariant(statusCode(StatusCode.BadRequest) and jsonBody[Status400Error]),
oneOfVariant(statusCode(StatusCode.InternalServerError) and jsonBody[Status500Error]),
oneOfVariant(statusCode(StatusCode.Unauthorized) and jsonBody[Unauthorized])
))
.serverSecurityLogic[Unit, IO](basicAuth(secretLocal))
.serverLogic(_ => request => ???)
to test auth logic and server logic in 2 different tests
val backendStub: SttpBackend[Future, Any] = TapirStubInterpreter(SttpBackendStub.asynchronousFuture)
.whenServerEndpoint(someServerEndpoint)
.thenRunLogic()
.backend()
this example is working only for Future
if anybody have an example for cats IO, please help
Upvotes: 0
Views: 59
Reputation: 8606
Here's an example test using ScalaTest:
//> using dep com.softwaremill.sttp.tapir::tapir-cats-effect:1.11.2
//> using dep com.softwaremill.sttp.tapir::tapir-sttp-stub-server:1.11.2
//> using dep com.softwaremill.sttp.tapir::tapir-cats:1.11.2
//> using dep com.softwaremill.sttp.client3::core:3.9.7
//> using dep org.scalatest::scalatest:3.2.19
package sttp.tapir.examples.testing
import cats.effect.IO
import org.scalatest.flatspec.AsyncFlatSpec
import org.scalatest.matchers.should.Matchers
import sttp.client3.*
import sttp.client3.testing.SttpBackendStub
import sttp.tapir.*
import sttp.tapir.integ.cats.effect.CatsMonadError
import sttp.tapir.server.ServerEndpoint
import sttp.tapir.server.stub.TapirStubInterpreter
import scala.concurrent.Future
class CatsServerStubInterpreter extends AsyncFlatSpec with Matchers:
it should "run greet users logic" in {
// given
// We need to pass an SttpBackendStub which is configured for the IO effect. One way to do it is to pass a
// MonadError implementation, as here. Alternatively, you can use any sttp-client cats-effect backend, and obtain
// the stub using its .stub method. For example: AsyncHttpClientCatsBackend.stub[IO]
val stubBackend: SttpBackend[IO, Any] = TapirStubInterpreter(SttpBackendStub[IO, Any](CatsMonadError()))
.whenServerEndpoint(UsersApi.greetUser)
.thenRunLogic()
.backend()
// when
val response = sttp.client3.basicRequest
.get(uri"http://test.com/api/users/greet")
.header("Authorization", "Bearer password")
.send(stubBackend)
// then
// since we are using ScalaTest, we need to run the IO effect, here - synchronously. When using an IO-aware test
// framework, this might get simplified.
import cats.effect.unsafe.implicits.global
response.unsafeRunSync().body shouldBe Right("hello user123")
}
// The API under test
object UsersApi:
val greetUser: ServerEndpoint[Any, IO] = endpoint.get
.in("api" / "users" / "greet")
.securityIn(auth.bearer[String]())
.out(stringBody)
.errorOut(stringBody)
.serverSecurityLogic(token => IO(if token == "password" then Right("user123") else Left("unauthorized")))
.serverLogic(user => _ => IO(Right(s"hello $user")))
Upvotes: 3