use crate::mock_server::MockServerBuilder;
use crate::mock_server::bare_server::BareMockServer;
use crate::mock_server::pool::{PooledMockServer, get_pooled_mock_server};
use crate::{MockGuard, Request, mock::Mock, verification::VerificationOutcome};
use log::debug;
use std::fmt::{Debug, Write};
use std::net::SocketAddr;
use std::ops::Deref;
#[derive(Debug)]
pub struct MockServer(InnerServer);
#[derive(Debug)]
pub(super) enum InnerServer {
Bare(BareMockServer),
Pooled(PooledMockServer),
}
impl Deref for InnerServer {
type Target = BareMockServer;
fn deref(&self) -> &Self::Target {
match self {
InnerServer::Bare(b) => b,
InnerServer::Pooled(p) => p,
}
}
}
impl MockServer {
pub(super) fn new(server: InnerServer) -> Self {
Self(server)
}
pub fn builder() -> MockServerBuilder {
MockServerBuilder::new()
}
pub async fn start() -> Self {
Self(InnerServer::Pooled(get_pooled_mock_server().await))
}
pub async fn register(&self, mock: Mock) {
self.0.register(mock).await;
}
pub async fn register_as_scoped(&self, mock: Mock) -> MockGuard {
self.0.register_as_scoped(mock).await
}
pub async fn reset(&self) {
self.0.reset().await;
}
pub async fn verify(&self) {
debug!("Verify mock expectations.");
let body_print_limit = self.0.body_print_limit().await;
if let VerificationOutcome::Failure(failed_verifications) = self.0.verify().await {
let received_requests_message = if let Some(received_requests) =
self.0.received_requests().await
{
if received_requests.is_empty() {
"The server did not receive any request.".into()
} else {
received_requests.iter().enumerate().fold(
"Received requests:\n".to_string(),
|mut message, (index, request)| {
_ = write!(message, "- Request #{}\n\t", index + 1,);
_ = request.print_with_limit(&mut message, body_print_limit);
message
},
)
}
} else {
"Enable request recording on the mock server to get the list of incoming requests as part of the panic message.".into()
};
let verifications_errors: String =
failed_verifications.iter().fold(String::new(), |mut s, m| {
_ = writeln!(s, "- {}", m.error_message());
s
});
let error_message = format!(
"Verifications failed:\n{verifications_errors}\n{received_requests_message}",
);
if std::thread::panicking() {
debug!("{}", &error_message);
} else {
panic!("{}", &error_message);
}
}
}
pub fn uri(&self) -> String {
self.0.uri()
}
pub fn address(&self) -> &SocketAddr {
self.0.address()
}
pub async fn received_requests(&self) -> Option<Vec<Request>> {
self.0.received_requests().await
}
}
impl Drop for MockServer {
fn drop(&mut self) {
futures::executor::block_on(self.verify());
}
}