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}