1use crate::Container;
4use crate::error::Error;
5
6pub trait Inject: Sized + Send + Sync {
64 fn inject(container: &Container) -> Result<Self, Error>;
65}
66
67impl<T: Default + Send + Sync> Inject for T {
68 #[inline]
69 fn inject(_: &Container) -> Result<Self, Error> {
70 Ok(Self::default())
71 }
72}
73
74#[macro_export]
121macro_rules! singleton {
122 ($($name:ident)*) => {
123 $(impl $crate::Inject for $name {
124 #[inline]
125 fn inject(_: &$crate::Container) -> Result<Self, $crate::error::Error> {
126 Err($crate::error::Error::ResolveFailed(stringify!($name)))
127 }
128 })*
129 };
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use crate::container::ContainerBuilder;
136 use std::sync::{Arc, Mutex};
137
138 #[derive(Default, Clone)]
139 struct SimpleService {
140 value: i32,
141 }
142
143 #[derive(Clone)]
144 struct ServiceWithDependency {
145 service: SimpleService,
146 multiplier: i32,
147 }
148
149 impl Inject for ServiceWithDependency {
150 fn inject(container: &Container) -> Result<Self, Error> {
151 let service = container.resolve::<SimpleService>()?;
152 Ok(Self {
153 service,
154 multiplier: 2,
155 })
156 }
157 }
158
159 #[derive(Clone)]
160 struct ComplexService {
161 dependency: ServiceWithDependency,
162 data: Arc<Mutex<Vec<String>>>,
163 }
164
165 impl Inject for ComplexService {
166 fn inject(container: &Container) -> Result<Self, Error> {
167 let dependency = container.resolve::<ServiceWithDependency>()?;
168 Ok(Self {
169 dependency,
170 data: Arc::new(Mutex::new(vec!["test".to_string()])),
171 })
172 }
173 }
174
175 #[derive(Debug)]
176 struct FailingService;
177
178 impl Inject for FailingService {
179 fn inject(_: &Container) -> Result<Self, Error> {
180 Err(Error::Other("Injection failed"))
181 }
182 }
183
184 #[derive(Debug)]
185 struct SingletonService;
186
187 singleton! {
188 SingletonService
189 }
190
191 #[test]
192 fn it_injects_default_service() {
193 let container = ContainerBuilder::new().build();
194
195 let result = SimpleService::inject(&container);
196
197 assert!(result.is_ok());
198 let service = result.unwrap();
199 assert_eq!(service.value, 0);
200 }
201
202 #[test]
203 fn it_injects_service_with_dependencies() {
204 let mut builder = ContainerBuilder::new();
205 builder.register_scoped::<SimpleService>();
206 let container = builder.build().create_scope();
207
208 let result = ServiceWithDependency::inject(&container);
209
210 assert!(result.is_ok());
211 let service = result.unwrap();
212 assert_eq!(service.service.value, 0);
213 assert_eq!(service.multiplier, 2);
214 }
215
216 #[test]
217 fn it_injects_complex_service_with_nested_dependencies() {
218 let mut builder = ContainerBuilder::new();
219 builder.register_scoped::<SimpleService>();
220 builder.register_scoped::<ServiceWithDependency>();
221 let container = builder.build().create_scope();
222
223 let result = ComplexService::inject(&container);
224
225 assert!(result.is_ok());
226 let service = result.unwrap();
227 assert_eq!(service.dependency.service.value, 0);
228 assert_eq!(service.dependency.multiplier, 2);
229 let data = service.data.lock().unwrap();
230 assert_eq!(data[0], "test");
231 }
232
233 #[test]
234 fn it_fails_when_dependency_not_registered() {
235 let container = ContainerBuilder::new().build();
236
237 let result = ServiceWithDependency::inject(&container);
238
239 assert!(result.is_err());
240 }
241
242 #[test]
243 fn it_handles_injection_errors() {
244 let container = ContainerBuilder::new().build();
245
246 let result = FailingService::inject(&container);
247
248 assert!(result.is_err());
249 match result.unwrap_err() {
250 Error::Other(msg) => assert_eq!(msg, "Injection failed"),
251 _ => panic!("Expected Other error"),
252 }
253 }
254
255 #[test]
256 fn it_uses_default_trait_implementation_for_inject() {
257 let container = ContainerBuilder::new().build();
258
259 let result = <SimpleService as Inject>::inject(&container);
261
262 assert!(result.is_ok());
263 let service = result.unwrap();
264 assert_eq!(service.value, 0);
265 }
266
267 #[test]
268 fn it_resolves_same_dependency_multiple_times() {
269 let mut builder = ContainerBuilder::new();
270 builder.register_scoped::<SimpleService>();
271 let container = builder.build().create_scope();
272
273 let result1 = ServiceWithDependency::inject(&container);
274 let result2 = ServiceWithDependency::inject(&container);
275
276 assert!(result1.is_ok());
277 assert!(result2.is_ok());
278
279 let service1 = result1.unwrap();
280 let service2 = result2.unwrap();
281
282 assert_eq!(service1.service.value, service2.service.value);
284 assert_eq!(service1.multiplier, service2.multiplier);
285 }
286
287 #[test]
288 fn it_works_with_different_service_lifetimes() {
289 let mut builder = ContainerBuilder::new();
290 builder.register_singleton(SimpleService { value: 100 });
291 builder.register_transient::<ServiceWithDependency>();
292 let container = builder.build();
293
294 let result1 = ServiceWithDependency::inject(&container);
295 let result2 = ServiceWithDependency::inject(&container);
296
297 assert!(result1.is_ok());
298 assert!(result2.is_ok());
299
300 let service1 = result1.unwrap();
301 let service2 = result2.unwrap();
302
303 assert_eq!(service1.service.value, 100);
305 assert_eq!(service2.service.value, 100);
306 }
307
308 #[test]
309 fn it_prevents_singleton_injection() {
310 let container = ContainerBuilder::new().build();
311
312 let result = SingletonService::inject(&container);
313
314 assert!(result.is_err());
315 match result.unwrap_err() {
316 Error::ResolveFailed(msg) => assert_eq!(msg, "SingletonService"),
317 _ => panic!("Expected ResolveFailed error with singleton message"),
318 }
319 }
320
321
322 #[test]
323 fn it_tests_send_sync_requirements() {
324 fn assert_send_sync<T: Send + Sync>() {}
325
326 assert_send_sync::<SimpleService>();
328 assert_send_sync::<ServiceWithDependency>();
329 assert_send_sync::<ComplexService>();
330 }
331}
332