Skip to main content

axum_test/
test_server_config.rs

1use crate::TestServer;
2use crate::TestServerBuilder;
3use crate::Transport;
4use crate::internals::ErrorMessage;
5use crate::transport_layer::IntoTransportLayer;
6use anyhow::Result;
7
8/// This is for customising the [`TestServer`](crate::TestServer) on construction.
9/// It implements [`Default`] to ease building.
10///
11/// ```rust
12/// use axum_test::TestServerConfig;
13///
14/// let config = TestServerConfig {
15///     save_cookies: true,
16///     ..TestServerConfig::default()
17/// };
18/// ```
19///
20/// These can be passed to `TestServer::new_with_config`:
21///
22/// ```rust
23/// # async fn test() -> Result<(), Box<dyn ::std::error::Error>> {
24/// #
25/// use axum::Router;
26/// use axum_test::TestServer;
27/// use axum_test::TestServerConfig;
28///
29/// let my_app = Router::new();
30///
31/// let config = TestServerConfig {
32///     save_cookies: true,
33///     ..TestServerConfig::default()
34/// };
35///
36/// // Build the Test Server
37/// let server = TestServer::new_with_config(my_app, config);
38/// #
39/// # Ok(())
40/// # }
41/// ```
42///
43#[derive(Debug, Clone, Eq, PartialEq)]
44pub struct TestServerConfig {
45    /// Which transport mode to use to process requests.
46    /// For setting if the server should use mocked http (which uses [`tower::util::Oneshot`](tower::util::Oneshot)),
47    /// or if it should run on a named or random IP address.
48    ///
49    /// The default is to use mocking, apart from services built using [`axum::extract::connect_info::IntoMakeServiceWithConnectInfo`](axum::extract::connect_info::IntoMakeServiceWithConnectInfo)
50    /// (this is because it needs a real TCP stream).
51    pub transport: Option<Transport>,
52
53    /// Set for the server to save cookies that are returned,
54    /// for use in future requests.
55    ///
56    /// This is useful for automatically saving session cookies (and similar)
57    /// like a browser would do.
58    ///
59    /// **Defaults** to false (being turned off).
60    pub save_cookies: bool,
61
62    /// Asserts that requests made to the test server,
63    /// will by default,
64    /// return a status code in the 2xx range.
65    ///
66    /// This can be overridden on a per request basis using
67    /// [`TestRequest::expect_failure()`](crate::TestRequest::expect_failure()).
68    ///
69    /// This is useful when making multiple requests at a start of test
70    /// which you presume should always work.
71    ///
72    /// **Defaults** to false (being turned off).
73    pub expect_success_by_default: bool,
74
75    /// If you make a request with a 'http://' scheme,
76    /// then it will ignore the Test Server's address.
77    ///
78    /// For example if the test server is running at `http://localhost:1234`,
79    /// and you make a request to `http://google.com`.
80    /// Then the request will go to `http://google.com`.
81    /// Ignoring the `localhost:1234` part.
82    ///
83    /// Turning this setting on will change this behaviour.
84    ///
85    /// After turning this on, the same request will go to
86    /// `http://localhost:1234/http://google.com`.
87    ///
88    /// **Defaults** to false (being turned off).
89    pub restrict_requests_with_http_scheme: bool,
90
91    /// Set the default content type for all requests created by the `TestServer`.
92    ///
93    /// This overrides the default 'best efforts' approach of requests.
94    pub default_content_type: Option<String>,
95}
96
97impl TestServerConfig {
98    /// Creates a default [`TestServerConfig`].
99    pub fn new() -> Self {
100        Default::default()
101    }
102
103    /// Builds a [`TestServer`] configured by this config.
104    ///
105    /// It is shorthand for calling [`TestServer::new_with_config`],
106    /// with config passed in.
107    ///
108    /// ```rust
109    /// # async fn test() -> Result<(), Box<dyn ::std::error::Error>> {
110    /// #
111    /// use axum::Router;
112    /// use axum_test::TestServer;
113    /// use axum_test::TestServerConfig;
114    ///
115    /// let app = Router::new();
116    /// let config = TestServerConfig {
117    ///     save_cookies: true,
118    ///     default_content_type: Some("application/json".to_string()),
119    ///     ..Default::default()
120    /// };
121    /// let server = config.build(app);
122    /// #
123    /// # Ok(())
124    /// # }
125    /// ```
126    ///
127    /// Note: this will panic if the [`TestServer`] cannot be built.
128    /// To catch the error use [`TestServerConfig::try_build`].
129    pub fn build<A>(self, app: A) -> TestServer
130    where
131        A: IntoTransportLayer,
132    {
133        self.try_build(app)
134            .error_message("Failed to build TestServer")
135    }
136
137    /// Attempts to build a [`TestServer`] from this config,
138    /// and returns an error if this fails.
139    pub fn try_build<A>(self, app: A) -> Result<TestServer>
140    where
141        A: IntoTransportLayer,
142    {
143        TestServer::try_new_with_config(app, self)
144    }
145}
146
147impl Default for TestServerConfig {
148    fn default() -> Self {
149        Self {
150            transport: None,
151            save_cookies: false,
152            expect_success_by_default: false,
153            restrict_requests_with_http_scheme: false,
154            default_content_type: None,
155        }
156    }
157}
158
159impl From<TestServerBuilder> for TestServerConfig {
160    fn from(builder: TestServerBuilder) -> Self {
161        builder.into_config()
162    }
163}