mongodb_integration/
mongodb_integration.rs1use rust_test_harness::{test, run_tests_with_config, TestConfig, ContainerConfig, before_each};
10use std::time::Duration;
11
12struct MongoClient {
14 container_id: String,
15 connected: bool,
16}
17
18impl MongoClient {
19 fn new(container_id: String) -> Self {
20 Self {
21 container_id,
22 connected: false,
23 }
24 }
25
26 fn connect(&mut self) -> Result<(), String> {
27 std::thread::sleep(Duration::from_millis(20));
29 self.connected = true;
30 Ok(())
31 }
32
33 fn disconnect(&mut self) -> Result<(), String> {
34 std::thread::sleep(Duration::from_millis(10));
36 self.connected = false;
37 Ok(())
38 }
39
40 fn insert_document(&self, collection: &str, document: &str) -> Result<(), String> {
41 if !self.connected {
42 return Err("Not connected to MongoDB".to_string());
43 }
44
45 std::thread::sleep(Duration::from_millis(5));
47 println!("๐ Inserted document into collection '{}': {}", collection, document);
48 Ok(())
49 }
50
51 fn find_documents(&self, collection: &str, query: &str) -> Result<Vec<String>, String> {
52 if !self.connected {
53 return Err("Not connected to MongoDB".to_string());
54 }
55
56 std::thread::sleep(Duration::from_millis(3));
58 println!("๐ Found documents in collection '{}' with query: {}", collection, query);
59
60 Ok(vec![
62 format!("Document 1 matching: {}", query),
63 format!("Document 2 matching: {}", query),
64 ])
65 }
66}
67
68fn main() {
69 println!("๐ณ MongoDB Integration Example with Container Hooks");
70 println!("==================================================");
71 println!();
72
73 let mongo_container = ContainerConfig::new("mongo:5.0")
75 .auto_port(27017) .env("MONGO_INITDB_ROOT_USERNAME", "admin")
77 .env("MONGO_INITDB_ROOT_PASSWORD", "password")
78 .name("test_mongodb")
79 .ready_timeout(Duration::from_secs(30));
80
81 println!("๐ Container Configuration:");
82 println!(" Image: {}", mongo_container.image);
83 println!(" Auto-ports: {:?}", mongo_container.auto_ports);
84 println!(" Environment: {:?}", mongo_container.env);
85 println!(" Name: {:?}", mongo_container.name);
86 println!(" Ready Timeout: {:?}", mongo_container.ready_timeout);
87 println!(" Auto-cleanup: {}", mongo_container.auto_cleanup);
88 println!();
89
90 let mongo_container_before = mongo_container.clone();
92
93 before_each(move |ctx| {
95 println!("๐ before_each: Starting MongoDB container...");
96
97 let container_info = mongo_container_before.start()
99 .map_err(|e| format!("Failed to start container: {}", e))?;
100
101 ctx.set_data("mongo_container_info", container_info.clone());
103
104 println!("โ
before_each: MongoDB container {} started", container_info.container_id);
106 println!("๐ Container exposed on: {}", container_info.ports_summary());
107 if let Some(primary_url) = container_info.primary_url() {
108 println!("๐ Primary URL: {}", primary_url);
109 }
110
111 Ok(())
112 });
113
114 let mongo_container_after = mongo_container.clone();
116 rust_test_harness::after_each(move |ctx| {
117 println!("๐ after_each: Stopping MongoDB container...");
118
119 let container_info = ctx.get_data::<rust_test_harness::ContainerInfo>("mongo_container_info")
121 .expect("Container info should be available");
122
123 mongo_container_after.stop(&container_info.container_id)
125 .map_err(|e| format!("Failed to stop container: {}", e))?;
126
127 println!("โ
after_each: MongoDB container {} stopped", container_info.container_id);
128 Ok(())
129 });
130
131 test("test_mongodb_basic_operations", |ctx| {
133 println!("๐งช Running test: test_mongodb_basic_operations");
134
135 let container_info = ctx.get_data::<rust_test_harness::ContainerInfo>("mongo_container_info")
137 .expect("Container info should be available");
138
139 println!("๐ Container {} is running on:", container_info.container_id);
141 println!(" Ports: {}", container_info.ports_summary());
142 if let Some(primary_url) = container_info.primary_url() {
143 println!(" Primary URL: {}", primary_url);
144 }
145
146 if let Some(host_port) = container_info.host_port_for(27017) {
148 println!(" MongoDB accessible at: localhost:{}", host_port);
149 }
150
151 let mut client = MongoClient::new(container_info.container_id.clone());
153
154 client.connect()?;
156
157 client.insert_document("users", r#"{"name": "John Doe", "email": "john@example.com"}"#)?;
159
160 let documents = client.find_documents("users", r#"{"name": "John Doe"}"#)?;
162 assert_eq!(documents.len(), 2);
163
164 client.disconnect()?;
166
167 println!("โ
test_mongodb_basic_operations passed");
168 Ok(())
169 });
170
171 test("test_mongodb_multiple_operations", |ctx| {
173 println!("๐งช Running test: test_mongodb_multiple_operations");
174
175 let container_info = ctx.get_data::<rust_test_harness::ContainerInfo>("mongo_container_info")
177 .expect("Container info should be available");
178
179 println!("๐ Container {} status:", container_info.container_id);
181 println!(" Active ports: {}", container_info.ports_summary());
182
183 let mut client = MongoClient::new(container_info.container_id.clone());
185
186 client.connect()?;
188
189 client.insert_document("products", r#"{"name": "Laptop", "price": 999.99}"#)?;
191 client.insert_document("products", r#"{"name": "Mouse", "price": 29.99}"#)?;
192 client.insert_document("products", r#"{"name": "Keyboard", "price": 79.99}"#)?;
193
194 let documents = client.find_documents("products", r#"{"price": {"$gt": 50}}"#)?;
196 assert_eq!(documents.len(), 2); client.disconnect()?;
200
201 println!("โ
test_mongodb_multiple_operations passed");
202 Ok(())
203 });
204
205 test("test_mongodb_error_handling", |ctx| {
207 println!("๐งช Running test: test_mongodb_error_handling");
208
209 let container_id = ctx.get_data::<String>("mongo_container_id")
211 .expect("Container ID should be available")
212 .to_string();
213
214 let client = MongoClient::new(container_id);
216
217 let result = client.insert_document("users", r#"{"name": "Test"}"#);
219 assert!(result.is_err());
220 assert_eq!(result.unwrap_err(), "Not connected to MongoDB");
221
222 println!("โ
test_mongodb_error_handling passed");
223 Ok(())
224 });
225
226 test("test_mongodb_performance", |ctx| {
228 println!("๐งช Running test: test_mongodb_performance");
229
230 let container_id = ctx.get_data::<String>("mongo_container_id")
232 .expect("Container ID should be available")
233 .to_string();
234
235 let mut client = MongoClient::new(container_id);
237
238 client.connect()?;
240
241 for i in 0..100 {
243 client.insert_document("bulk_data", &format!(r#"{{"index": {}, "data": "bulk_item_{}"}}"#, i, i))?;
244 }
245
246 let documents = client.find_documents("bulk_data", r#"{"index": {"$lt": 50}}"#)?;
248 assert_eq!(documents.len(), 2); client.disconnect()?;
252
253 println!("โ
test_mongodb_performance passed");
254 Ok(())
255 });
256
257 println!("\n๐ Running MongoDB integration tests...");
258 println!(" Each test will get a fresh MongoDB container via before_each");
259 println!(" Each test will clean up its container via after_each");
260 println!();
261
262 let config = TestConfig {
264 skip_hooks: Some(false),
265 ..Default::default()
266 };
267
268 let result = run_tests_with_config(config);
269
270 println!("\n๐ Test Results:");
271 if result == 0 {
272 println!("โ
All MongoDB integration tests passed!");
273 println!("๐ฏ Container lifecycle management working correctly");
274 println!("๐ณ Each test got its own MongoDB container");
275 println!("๐งน Each test cleaned up its container properly");
276 } else {
277 println!("โ Some tests failed");
278 }
279
280 println!("\n๐ก Key Benefits of this approach:");
281 println!(" โข Clean separation of concerns");
282 println!(" โข Each test gets a fresh container");
283 println!(" โข Automatic cleanup via after_each");
284 println!(" โข Easy to configure containers");
285 println!(" โข No complex global state management");
286}