use std::{any::type_name, sync::Arc};
use async_trait::async_trait;
use reqwest::Request;
use reqwest_middleware::{RequestBuilder, RequestInitialiser};
use crate::ResponseBody;
#[async_trait]
pub trait Responder: 'static + Send + Sync {
fn type_name(&self) -> &str {
type_name::<Self>()
}
async fn handle(&self, req: Request) -> anyhow::Result<ResponseBody>;
}
#[async_trait]
impl<F> Responder for F
where
F: 'static + Send + Sync,
F: Fn(Request) -> anyhow::Result<ResponseBody>,
{
async fn handle(&self, req: Request) -> anyhow::Result<ResponseBody> {
self(req)
}
}
#[derive(Clone)]
pub struct MockServer {
inner: Arc<dyn Responder>,
}
impl MockServer {
pub fn new(reply: impl Responder) -> Self {
Self {
inner: Arc::new(reply),
}
}
}
#[async_trait]
impl Responder for MockServer {
fn type_name(&self) -> &str {
self.inner.type_name()
}
async fn handle(&self, req: Request) -> anyhow::Result<ResponseBody> {
self.inner.handle(req).await
}
}
#[async_trait]
impl RequestInitialiser for MockServer {
fn init(&self, req: RequestBuilder) -> RequestBuilder {
req.with_extension(self.clone())
}
}