tower_async_test/
mock.rs

1//! This module provides the [`Mock`] [`tower_async_service::Service`] that is used
2//! by this crate as the core [`tower_async_service::Service`] to help you
3//! test your own [`tower_async_layer::Layer`]s.
4//!
5//! The [`Mock`] [`tower_async_service::Service`] is to be used
6//! in tests to assert that a [`tower_async_service::Service`] wrapped
7//! by a [`tower_async_layer::Layer`] receives the expected requests,
8//! and to send back responses or errors.
9//!
10//! You cannot use the [`Mock`] [`tower_async_service::Service`] directly,
11//! but instead use it automatically for any _test_ spawned
12//! using the [`crate::Builder`] and specifically its [`crate::Builder::test`] method.
13
14use std::{collections::VecDeque, sync::Arc};
15
16use tokio::sync::Mutex;
17use tower_async_service::Service;
18
19/// The [`Mock`] [`tower_async_service::Service`] is to be used
20/// in tests to assert that a [`tower_async_service::Service`] wrapped
21/// by a [`tower_async_layer::Layer`] receives the expected requests,
22/// and to send back responses or errors.
23///
24/// You cannot use the [`Mock`] [`tower_async_service::Service`] directly,
25/// but instead use it automatically for any _test_ spawned
26/// using the [`crate::Builder`] and specifically its [`crate::Builder::test`] method.
27#[derive(Debug)]
28pub struct Mock<Request, Response, Error> {
29    handle: SyncHandle<Request, Response, Error>,
30}
31
32/// Creates a new mock `Service` and with the default driver implementation,
33/// which can be used to assert that the `Service` receives the expected requests,
34/// and to send back responses.
35pub(crate) fn spawn<Request, Response, Error>() -> (
36    Mock<Request, Response, Error>,
37    SyncHandle<Request, Response, Error>,
38)
39where
40    Request: Send + Sync,
41    Response: Send + Sync,
42    Error: Send + Sync,
43{
44    let handle = Arc::new(Mutex::new(Handle::new()));
45    let mock = Mock {
46        handle: handle.clone(),
47    };
48    (mock, handle)
49}
50
51impl<Request, Response, Error> Service<Request> for Mock<Request, Response, Error> {
52    type Response = Response;
53    type Error = Error;
54
55    async fn call(&self, request: Request) -> Result<Self::Response, Self::Error> {
56        let mut handle = self.handle.lock().await;
57        handle.push_request(request);
58        handle.pop_result()
59    }
60}
61
62/// A Sync `Handle` to a mock `Service`.
63pub(crate) type SyncHandle<Request, Response, Error> = Arc<Mutex<Handle<Request, Response, Error>>>;
64
65/// The default `Handle` implementation.
66#[derive(Debug)]
67pub(crate) struct Handle<Request, Response, Error> {
68    requests: VecDeque<Request>,
69    results: VecDeque<Result<Response, Error>>,
70}
71
72impl<Request, Response, Error> Handle<Request, Response, Error> {
73    /// Returns a new `Handle`, only usable once you inserted some results.
74    pub(crate) fn new() -> Self {
75        Self {
76            requests: VecDeque::new(),
77            results: VecDeque::new(),
78        }
79    }
80
81    /// Inserts a new request that was received by the mock `Service`.
82    pub(crate) fn push_request(&mut self, request: Request) {
83        self.requests.push_back(request);
84    }
85
86    /// Inserts a new result to be returned by the mock `Service`.
87    pub(crate) fn push_result(&mut self, result: Result<Response, Error>) {
88        self.results.push_back(result);
89    }
90
91    /// Returns the oldest request received by the mock `Service`.
92    ///
93    /// # Panics
94    ///
95    /// Panics if no request has been received.
96    pub(crate) fn pop_request(&mut self) -> Request {
97        self.requests.pop_front().unwrap()
98    }
99
100    /// Returns the oldest result to be returned by the mock `Service`.
101    ///
102    /// # Panics
103    ///
104    /// Panics if no result has been inserted.
105    pub(crate) fn pop_result(&mut self) -> Result<Response, Error> {
106        self.results.pop_front().unwrap()
107    }
108}
109
110impl<Request, Response, Error> Default for Handle<Request, Response, Error> {
111    fn default() -> Self {
112        Self::new()
113    }
114}