All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sttp.client4.testing.RecordingBackend.scala Maven / Gradle / Ivy

There is a newer version: 4.0.0-M19
Show newest version
package sttp.client4.testing

import java.util.concurrent.atomic.AtomicReference
import java.util.function.UnaryOperator
import sttp.client4._
import sttp.monad.syntax._

import scala.util.{Failure, Success, Try}
import sttp.capabilities.Effect
import sttp.client4.wrappers.DelegateBackend

trait RecordingBackend {
  type RequestAndResponse = (GenericRequest[_, _], Try[Response[_]])
  def allInteractions: List[RequestAndResponse]
}

abstract class AbstractRecordingBackend[F[_], P](delegate: GenericBackend[F, P])
    extends DelegateBackend[F, P](delegate)
    with RecordingBackend {

  private val _allInteractions = new AtomicReference[Vector[RequestAndResponse]](Vector())

  private def addInteraction(request: GenericRequest[_, _], response: Try[Response[_]]): Unit =
    _allInteractions.updateAndGet(new UnaryOperator[Vector[RequestAndResponse]] {
      override def apply(t: Vector[RequestAndResponse]): Vector[RequestAndResponse] = t.:+((request, response))
    })

  override def send[T](request: GenericRequest[T, P with Effect[F]]): F[Response[T]] =
    delegate
      .send(request)
      .map { response =>
        addInteraction(request, Success(response))
        response
      }
      .handleError { case e: Exception =>
        addInteraction(request, Failure(e))
        monad.error(e)
      }

  override def allInteractions: List[RequestAndResponse] = _allInteractions.get().toList
}

object RecordingBackend {
  def apply(delegate: SyncBackend): SyncBackend with RecordingBackend =
    new AbstractRecordingBackend(delegate) with SyncBackend {}

  def apply[F[_]](delegate: Backend[F]): Backend[F] with RecordingBackend =
    new AbstractRecordingBackend(delegate) with Backend[F] {}

  def apply[F[_]](delegate: WebSocketBackend[F]): WebSocketBackend[F] with RecordingBackend =
    new AbstractRecordingBackend(delegate) with WebSocketBackend[F] {}

  def apply[F[_], S](delegate: StreamBackend[F, S]): StreamBackend[F, S] with RecordingBackend =
    new AbstractRecordingBackend(delegate) with StreamBackend[F, S] {}

  def apply[F[_], S](delegate: WebSocketStreamBackend[F, S]): WebSocketStreamBackend[F, S] with RecordingBackend =
    new AbstractRecordingBackend(delegate) with WebSocketStreamBackend[F, S] {}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy