Skip to main content

armature_testing/
lib.rs

1//! Testing utilities for Armature framework.
2//!
3//! This crate provides comprehensive testing tools for Armature applications.
4//!
5//! ## Features
6//!
7//! - ๐Ÿงช **TestApp** - Integration test builder
8//! - ๐Ÿ“ก **TestClient** - HTTP test client
9//! - ๐ŸŽญ **MockService** - Service mocking
10//! - ๐Ÿ‘๏ธ **Spy** - Method call tracking
11//! - โœ… **Assertions** - Fluent test assertions
12//! - ๐Ÿ—„๏ธ **Integration Helpers** - Database setup/teardown
13//! - ๐Ÿณ **Docker Containers** - Docker-based testing
14//! - ๐Ÿ“Š **Load Testing** - Performance test utilities
15//! - ๐Ÿ“œ **Contract Testing** - Pact/consumer-driven contracts
16//!
17//! ## Quick Start
18//!
19//! ```no_run
20//! use armature_testing::*;
21//! use armature_core::{HttpRequest, HttpResponse, Error};
22//!
23//! # tokio_test::block_on(async {
24//! // Create a test app
25//! let app = TestAppBuilder::new()
26//!     .with_route("/hello", |_req| async {
27//!         Ok(HttpResponse::ok().with_body(b"Hello!".to_vec()))
28//!     })
29//!     .build();
30//!
31//! // Make test requests
32//! let client = app.client();
33//! let response = client.get("/hello").await;
34//! assert_eq!(response.status(), Some(200));
35//! assert_eq!(response.body_string(), Some("Hello!".to_string()));
36//! # });
37//! ```
38//!
39//! ## Testing Controllers
40//!
41//! ```no_run
42//! use armature_testing::*;
43//! use armature_core::{HttpRequest, HttpResponse, Error};
44//!
45//! # tokio_test::block_on(async {
46//! let app = TestAppBuilder::new()
47//!     .with_route("/api/users", |_req| async {
48//!         Ok(HttpResponse::ok().with_json(&serde_json::json!({
49//!             "users": ["Alice", "Bob"]
50//!         }))?)
51//!     })
52//!     .build();
53//!
54//! let client = app.client();
55//! let response = client.get("/api/users").await;
56//! let json: serde_json::Value = response.body_json().unwrap();
57//! assert_eq!(json["users"][0], "Alice");
58//! # });
59//! ```
60//!
61//! ## Mock Services
62//!
63//! ```
64//! use armature_testing::MockService;
65//!
66//! // Create a mock service
67//! let mock = MockService::<String>::new();
68//! mock.record_call("get_user");
69//!
70//! // Verify calls
71//! assert_eq!(mock.call_count(), 1);
72//! assert!(mock.was_called("get_user"));
73//! ```
74//!
75//! ## Assertions
76//!
77//! ```
78//! use armature_testing::*;
79//! use armature_core::HttpResponse;
80//!
81//! let response = HttpResponse::ok()
82//!     .with_header("Content-Type".to_string(), "application/json".to_string())
83//!     .with_body(b"{\"status\":\"ok\"}".to_vec());
84//!
85//! let test_response = TestResponse::Success(response);
86//!
87//! // Assert status
88//! assert_status(&test_response, 200);
89//!
90//! // Assert headers
91//! assert_header(&test_response, "Content-Type", "application/json");
92//! ```
93//!
94//! ## Integration Testing with Database
95//!
96//! ```rust,ignore
97//! use armature_testing::integration::*;
98//! use std::sync::Arc;
99//!
100//! // Implement DatabaseTestHelper for your database
101//! struct MyDbHelper;
102//!
103//! #[async_trait]
104//! impl DatabaseTestHelper for MyDbHelper {
105//!     async fn setup(&self) -> Result<(), IntegrationTestError> {
106//!         // Create tables, seed data
107//!         Ok(())
108//!     }
109//!
110//!     async fn teardown(&self) -> Result<(), IntegrationTestError> {
111//!         // Clean up
112//!         Ok(())
113//!     }
114//! }
115//!
116//! // Use in tests
117//! let fixture = TestFixture::new(Arc::new(MyDbHelper));
118//! fixture.run_test(|| async {
119//!     // Your test code
120//!     Ok(())
121//! }).await?;
122//! ```
123//!
124//! ## Docker Test Containers
125//!
126//! ```rust,ignore
127//! use armature_testing::docker::*;
128//!
129//! // Start Postgres container
130//! let config = PostgresContainer::config("testdb", "user", "pass");
131//! let mut container = DockerContainer::new(config);
132//! container.start().await?;
133//!
134//! // Run tests...
135//!
136//! // Container automatically stops on drop
137//! ```
138//!
139//! ## Load Testing
140//!
141//! ```rust,ignore
142//! use armature_testing::load::*;
143//!
144//! let config = LoadTestConfig::new(10, 1000); // 10 concurrent, 1000 requests
145//! let runner = LoadTestRunner::new(config, || async {
146//!     // Your test code
147//!     Ok(())
148//! });
149//!
150//! let stats = runner.run().await?;
151//! stats.print();
152//! ```
153//!
154//! ## Contract Testing
155//!
156//! ```rust,ignore
157//! use armature_testing::contract::*;
158//!
159//! // Create a contract
160//! let request = ContractRequest::new(ContractMethod::Get, "/api/users/1");
161//! let response = ContractResponse::new(200)
162//!     .with_body(serde_json::json!({"id": 1, "name": "Alice"}));
163//!
164//! let mut builder = ContractBuilder::new("Frontend", "Backend");
165//! builder.add_interaction(ContractInteraction::new(
166//!     "get user by ID",
167//!     request,
168//!     response,
169//! ));
170//!
171//! let contract = builder.build();
172//!
173//! // Save contract
174//! let manager = ContractManager::new(PathBuf::from("./pacts"));
175//! manager.save(&contract)?;
176//! ```
177
178mod assertions;
179mod mock;
180mod test_app;
181mod test_client;
182mod test_container;
183
184// New modules
185pub mod contract;
186pub mod docker;
187pub mod integration;
188pub mod load;
189
190pub use assertions::{assert_header, assert_json, assert_status};
191pub use mock::{MockController, MockProvider, MockService};
192pub use test_app::{TestApp, TestAppBuilder};
193pub use test_client::{TestClient, TestResponse};
194pub use test_container::TestContainer;
195
196// Re-export common testing utilities
197pub use tokio::test as tokio_test;
198
199/// Prelude for common imports.
200///
201/// ```
202/// use armature_testing::prelude::*;
203/// ```
204pub mod prelude {
205    pub use crate::assertions::{assert_header, assert_json, assert_status};
206    pub use crate::mock::{MockController, MockProvider, MockService};
207    pub use crate::test_app::{TestApp, TestAppBuilder};
208    pub use crate::test_client::{TestClient, TestResponse};
209    pub use crate::test_container::TestContainer;
210
211    // Integration testing
212    pub use crate::integration::{DatabaseTestHelper, IntegrationTestError, TestFixture};
213
214    // Docker testing
215    pub use crate::docker::{ContainerConfig, DockerContainer};
216
217    // Load testing
218    pub use crate::load::{LoadTestConfig, LoadTestRunner, LoadTestStats};
219
220    // Contract testing
221    pub use crate::contract::{
222        Contract, ContractBuilder, ContractInteraction, ContractManager, ContractMethod,
223        ContractRequest, ContractResponse,
224    };
225}
226
227#[cfg(test)]
228mod tests {
229    #[test]
230    fn test_module_exports() {
231        // Ensure module compiles
232    }
233}