armature_testing/test_app.rs
1// Test Application Builder
2
3use armature_core::{Application, Container, Module, Provider, Router};
4use std::sync::Arc;
5
6/// Test application for integration testing
7pub struct TestApp {
8 pub app: Application,
9 pub container: Arc<Container>,
10}
11
12impl TestApp {
13 /// Create a new test application
14 pub fn new(container: Container, router: Router) -> Self {
15 let container_arc = Arc::new(container);
16 let app = Application::new(Container::new(), router);
17 Self {
18 app,
19 container: container_arc,
20 }
21 }
22
23 /// Get a service from the container
24 pub fn get<T: Provider + Clone + 'static>(&self) -> Option<T> {
25 // This would need actual container implementation
26 None
27 }
28
29 /// Create a test client for making requests
30 ///
31 /// # Examples
32 ///
33 /// ```no_run
34 /// use armature_testing::TestAppBuilder;
35 /// use armature_core::HttpResponse;
36 ///
37 /// # tokio_test::block_on(async {
38 /// let app = TestAppBuilder::new()
39 /// .with_route("/test", |_req| async {
40 /// Ok(HttpResponse::ok().with_body(b"OK".to_vec()))
41 /// })
42 /// .build();
43 ///
44 /// let client = app.client();
45 /// let response = client.get("/test").await;
46 /// assert_eq!(response.status(), Some(200));
47 /// # });
48 /// ```
49 pub fn client(&self) -> crate::TestClient {
50 crate::TestClient::new(self.app.router.clone())
51 }
52}
53
54/// Builder for test applications.
55///
56/// Provides a fluent API for creating test applications with custom
57/// routes, services, and configuration.
58///
59/// # Examples
60///
61/// Basic test app:
62///
63/// ```no_run
64/// use armature_testing::TestAppBuilder;
65/// use armature_core::{HttpResponse, Error};
66///
67/// # tokio_test::block_on(async {
68/// let app = TestAppBuilder::new()
69/// .with_route("/test", |_req| async {
70/// Ok(HttpResponse::ok().with_body(b"test".to_vec()))
71/// })
72/// .build();
73///
74/// let client = app.client();
75/// let response = client.get("/test").await;
76/// assert_eq!(response.status(), Some(200));
77/// # });
78/// ```
79pub struct TestAppBuilder {
80 container: Container,
81 router: Router,
82}
83
84impl TestAppBuilder {
85 /// Create a new test app builder
86 pub fn new() -> Self {
87 Self {
88 container: Container::new(),
89 router: Router::new(),
90 }
91 }
92
93 /// Register a provider
94 pub fn register<T: Provider + Clone + 'static>(self, provider: T) -> Self {
95 self.container.register(provider);
96 self
97 }
98
99 /// Add a module
100 pub fn add_module<M: Module>(self, _module: M) -> Self {
101 // Module registration logic
102 self
103 }
104
105 /// Set custom container
106 pub fn with_container(self, container: Container) -> Self {
107 Self { container, ..self }
108 }
109
110 /// Set custom router
111 pub fn with_router(self, router: Router) -> Self {
112 Self { router, ..self }
113 }
114
115 /// Add a test route with a handler
116 ///
117 /// # Examples
118 ///
119 /// ```no_run
120 /// use armature_testing::TestAppBuilder;
121 /// use armature_core::HttpResponse;
122 ///
123 /// let app = TestAppBuilder::new()
124 /// .with_route("/api/health", |_req| async {
125 /// Ok(HttpResponse::ok().with_body(b"OK".to_vec()))
126 /// })
127 /// .build();
128 /// ```
129 pub fn with_route<F, Fut>(mut self, path: &str, handler: F) -> Self
130 where
131 F: Fn(armature_core::HttpRequest) -> Fut + Send + Sync + Clone + 'static,
132 Fut: std::future::Future<Output = Result<armature_core::HttpResponse, armature_core::Error>>
133 + Send
134 + 'static,
135 {
136 use armature_core::{HttpMethod, Route};
137 // Use the optimized Route::new which enables handler monomorphization
138 self.router
139 .add_route(Route::new(HttpMethod::GET, path, handler));
140 self
141 }
142
143 /// Build the test application
144 pub fn build(self) -> TestApp {
145 TestApp::new(self.container, self.router)
146 }
147}
148
149impl Default for TestAppBuilder {
150 fn default() -> Self {
151 Self::new()
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158
159 #[test]
160 fn test_builder_creation() {
161 let _builder = TestAppBuilder::new();
162 }
163
164 #[test]
165 fn test_app_creation() {
166 let builder = TestAppBuilder::new();
167 let _app = builder.build();
168 }
169}