mod container;
mod error;
mod factory;
#[cfg(feature = "ffi")]
pub mod ffi;
#[cfg(feature = "logging")]
pub mod logging;
mod provider;
mod scope;
mod storage;
pub mod typed;
pub mod verified;
#[cfg(feature = "perfect-hash")]
pub use storage::FrozenStorage;
pub use container::*;
pub use error::*;
pub use factory::*;
pub use provider::*;
pub use scope::*;
#[cfg(feature = "logging")]
pub use tracing::{debug, error, info, trace, warn};
#[cfg(feature = "derive")]
pub use dependency_injector_derive::{Inject, Service, TypedRequire};
pub use std::sync::Arc;
pub mod prelude {
pub use crate::{
BatchBuilder, BatchRegistrar, Container, DiError, Factory, Injectable, Lifetime,
PooledScope, Provider, Result, Scope, ScopePool, ScopedContainer,
};
pub use std::sync::Arc;
pub use crate::typed::{
DeclaresDeps, DepsPresent, Has, HasService, HasType, Reg, TypedBuilder, TypedContainer,
};
pub use crate::verified::{Resolvable, Service, ServiceModule, ServiceProvider};
#[cfg(feature = "derive")]
pub use crate::{Inject, Service as ServiceDerive, TypedRequire};
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicU32, Ordering};
#[derive(Clone)]
struct Database {
url: String,
}
#[allow(dead_code)]
#[derive(Clone)]
struct UserService {
name: String,
}
#[test]
fn test_singleton_registration() {
let container = Container::new();
container.singleton(Database { url: "test".into() });
let db = container.get::<Database>().unwrap();
assert_eq!(db.url, "test");
}
#[test]
fn test_multiple_resolve_same_instance() {
let container = Container::new();
container.singleton(Database { url: "test".into() });
let db1 = container.get::<Database>().unwrap();
let db2 = container.get::<Database>().unwrap();
assert!(Arc::ptr_eq(&db1, &db2));
}
#[test]
fn test_transient_creates_new_instance() {
static COUNTER: AtomicU32 = AtomicU32::new(0);
#[derive(Clone)]
struct Counter(u32);
let container = Container::new();
container.transient(|| Counter(COUNTER.fetch_add(1, Ordering::SeqCst)));
let c1 = container.get::<Counter>().unwrap();
let c2 = container.get::<Counter>().unwrap();
assert_ne!(c1.0, c2.0);
}
#[test]
fn test_lazy_singleton() {
static CREATED: AtomicU32 = AtomicU32::new(0);
#[derive(Clone)]
struct LazyService;
let container = Container::new();
container.lazy(|| {
CREATED.fetch_add(1, Ordering::SeqCst);
LazyService
});
assert_eq!(CREATED.load(Ordering::SeqCst), 0);
let _ = container.get::<LazyService>().unwrap();
assert_eq!(CREATED.load(Ordering::SeqCst), 1);
let _ = container.get::<LazyService>().unwrap();
assert_eq!(CREATED.load(Ordering::SeqCst), 1);
}
#[test]
fn test_scoped_container() {
let root = Container::new();
root.singleton(Database { url: "root".into() });
let child = root.scope();
child.singleton(UserService {
name: "child".into(),
});
assert!(child.contains::<Database>());
assert!(child.contains::<UserService>());
assert!(root.contains::<Database>());
assert!(!root.contains::<UserService>());
}
#[test]
fn test_not_found_error() {
let container = Container::new();
let result = container.get::<Database>();
assert!(result.is_err());
}
#[test]
fn test_override_in_scope() {
let root = Container::new();
root.singleton(Database {
url: "production".into(),
});
let test_scope = root.scope();
test_scope.singleton(Database { url: "test".into() });
let root_db = root.get::<Database>().unwrap();
assert_eq!(root_db.url, "production");
let child_db = test_scope.get::<Database>().unwrap();
assert_eq!(child_db.url, "test");
}
}