From 821b61084cb1d2da6d275f19fbcf2fa6a31f1c0b Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Wed, 6 Nov 2024 19:52:23 +0000 Subject: [PATCH] Use generics to separate mocked from unmocked --- src/net/mock.rs | 77 ------------------------------------- src/net/mod.rs | 10 ++--- src/net/system.rs | 96 ++++++++++++++++++++++++++++++++++++++--------- tests/net.rs | 9 ++--- 4 files changed, 88 insertions(+), 104 deletions(-) delete mode 100644 src/net/mock.rs diff --git a/src/net/mock.rs b/src/net/mock.rs deleted file mode 100644 index d9e9861..0000000 --- a/src/net/mock.rs +++ /dev/null @@ -1,77 +0,0 @@ -// -use super::{Error, Net, Result}; - -#[derive(Debug)] -struct Plan { - request: reqwest::Request, - response: reqwest::Response, -} - -#[derive(Default, Debug)] -pub struct MockNet { - plans: Vec, -} -impl MockNet { - pub(crate) fn new() -> Self { - Self::default() - } - - pub fn into_net(self) -> Net { - Net::mock(self) - } - - pub fn client(&self) -> reqwest::Client { - reqwest::Client::new() - } - - pub fn response(&self) -> http::response::Builder { - http::Response::builder() - } - - pub fn on(&mut self, request: reqwest::Request) -> OnRequest { - OnRequest { - mock: self, - request, - } - } - - fn _on(&mut self, request: reqwest::Request, response: reqwest::Response) { - self.plans.push(Plan { request, response }) - } - - pub(crate) async fn send( - &mut self, - request: reqwest::RequestBuilder, - ) -> Result { - let request = request.build()?; - let index = self.plans.iter().position(|plan| { - // TODO: add support or only matching on selected criteria - plan.request.method() == request.method() - && plan.request.url() == request.url() - && match (plan.request.body(), request.body()) { - (None, None) => true, - (Some(plan), Some(request)) => plan.as_bytes() == request.as_bytes(), - _ => false, - } - && plan.request.headers() == request.headers() - }); - match index { - Some(i) => Ok(self.plans.remove(i).response), - None => Err(Error::UnexpectedMockRequest(request)), - } - } - - pub fn assert(&self) -> Result<()> { - todo!() - } -} - -pub struct OnRequest<'mock> { - mock: &'mock mut MockNet, - request: reqwest::Request, -} -impl<'mock> OnRequest<'mock> { - pub fn response(self, response: reqwest::Response) { - self.mock._on(self.request, response) - } -} diff --git a/src/net/mod.rs b/src/net/mod.rs index 5fd2654..601bc60 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -2,21 +2,21 @@ //! //! -mod mock; mod system; mod result; pub use result::{Error, Result}; pub use system::Net; +use system::{Mocked, Unmocked}; /// Creates a new `Net`. -pub const fn new() -> Net { - Net::new() +pub const fn new() -> Net { + Net::::new() } /// Creates a new `MockNet` for use in tests. -pub fn mock() -> mock::MockNet { - mock::MockNet::new() +pub fn mock() -> Net { + Net::::new() } diff --git a/src/net/system.rs b/src/net/system.rs index 47add97..206ad1f 100644 --- a/src/net/system.rs +++ b/src/net/system.rs @@ -1,31 +1,93 @@ +use std::marker::PhantomData; + // -use super::{mock::MockNet, Error}; +use super::{Error, Result}; -pub struct Net { - mock: Option, -} -impl Net { - pub(crate) const fn mock(mock: MockNet) -> Self { - Self { mock: Some(mock) } - } +pub trait NetType {} +pub struct Mocked; +impl NetType for Mocked {} +pub struct Unmocked; +impl NetType for Unmocked {} + +type Plans = Vec; + +#[derive(Debug)] +pub struct Plan { + request: reqwest::Request, + response: reqwest::Response, } -impl Net { - +pub struct Net { + _type: PhantomData, + plans: Plans, +} +impl Net { pub(crate) const fn new() -> Self { - Self { mock: None } + Self { + _type: PhantomData, + plans: vec![], + } } + pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result { + request.send().await.map_err(Error::from) + } +} + +impl Net { pub fn client(&self) -> reqwest::Client { reqwest::Client::new() } - - pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result { - if let Some(mock) = &mut self.mock { - mock.send(request).await - } else { - request.send().await.map_err(Error::from) +} +impl Net { + pub(crate) const fn new() -> Self { + Self { + _type: PhantomData, + plans: vec![], } } + pub async fn send(&mut self, request: reqwest::RequestBuilder) -> Result { + let request = request.build()?; + let index = self.plans.iter().position(|plan| { + // TODO: add support or only matching on selected criteria + plan.request.method() == request.method() + && plan.request.url() == request.url() + && match (plan.request.body(), request.body()) { + (None, None) => true, + (Some(plan), Some(request)) => plan.as_bytes() == request.as_bytes(), + _ => false, + } + && plan.request.headers() == request.headers() + }); + match index { + Some(i) => Ok(self.plans.remove(i).response), + None => Err(Error::UnexpectedMockRequest(request)), + } + } + pub fn response(&self) -> http::response::Builder { + http::Response::builder() + } + + pub fn on(&mut self, request: reqwest::Request) -> OnRequest { + OnRequest { net: self, request } + } + + fn _on(&mut self, request: reqwest::Request, response: reqwest::Response) { + self.plans.push(Plan { request, response }) + } + + pub fn assert(&self) -> Result<()> { + todo!() + } +} + +pub struct OnRequest<'net> { + net: &'net mut Net, + request: reqwest::Request, +} +impl<'net> OnRequest<'net> { + pub fn response(self, response: reqwest::Response) { + self.net._on(self.request, response) + } } diff --git a/tests/net.rs b/tests/net.rs index da8d677..00253a2 100644 --- a/tests/net.rs +++ b/tests/net.rs @@ -8,15 +8,14 @@ mod get { #[tokio::test] async fn test() -> TestResult { - let mut net_mock = kxio::net::mock(); + let mut net = kxio::net::mock(); let url = "https://www.example.com"; - let request = net_mock.client().get(url).build()?; - let my_response = net_mock.response().status(200).body("OK").unwrap(); + let request = net.client().get(url).build()?; + let my_response = net.response().status(200).body("OK").unwrap(); - net_mock.on(request).response(my_response.clone().into()); + net.on(request).response(my_response.clone().into()); - let mut net = net_mock.into_net(); let client = net.client(); let response = net.send(client.get(url)).await?;