use crate::container::descriptor::ServiceId;
use crate::container::{DependencyResolver, Injectable, IocContainer, ServiceBinder};
use crate::errors::CoreError;
use std::sync::Arc;
#[derive(Default)]
struct TestService;
#[derive(Default)]
struct TestInjectableOnlyService;
impl Injectable for TestInjectableOnlyService {
fn dependencies() -> Vec<ServiceId> {
vec![]
}
fn create<R: DependencyResolver>(_resolver: &R) -> Result<Self, CoreError> {
Ok(TestInjectableOnlyService::default())
}
}
#[derive(Default)]
struct TestInjectableService {
#[allow(dead_code)]
dependency: Arc<TestService>,
}
impl TestInjectableService {
pub fn new(dependency: Arc<TestService>) -> Self {
Self { dependency }
}
}
impl Injectable for TestInjectableService {
fn dependencies() -> Vec<ServiceId> {
vec![ServiceId::of::<TestService>()]
}
fn create<R: DependencyResolver>(resolver: &R) -> Result<Self, CoreError> {
let dependency = resolver.resolve::<TestService>()?;
Ok(TestInjectableService::new(dependency))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factory_service_resolved_correctly() {
let mut container = IocContainer::new();
container.bind::<TestService, TestService>();
container.build().unwrap();
let service = container.resolve::<TestService>().unwrap();
assert!(Arc::strong_count(&service) >= 1);
}
#[test]
fn test_autowired_service_resolved_correctly() {
let mut container = IocContainer::new();
container
.bind::<TestService, TestService>()
.bind_injectable::<TestInjectableService>();
container.build().unwrap();
let service = container
.resolve_injectable::<TestInjectableService>()
.unwrap();
assert!(Arc::strong_count(&service) >= 1);
}
#[test]
fn test_autowired_service_wrong_resolution_method_fails() {
let mut container = IocContainer::new();
container
.bind::<TestService, TestService>()
.bind_injectable::<TestInjectableService>();
container.build().unwrap();
let result = container.resolve::<TestInjectableService>();
assert!(result.is_err());
if let Err(CoreError::InvalidServiceDescriptor { message }) = result {
assert!(message.contains("is marked as auto-wired"));
assert!(message.contains("resolve_injectable"));
} else {
panic!("Expected InvalidServiceDescriptor error with auto-wiring message");
}
}
#[test]
fn test_factory_service_wrong_resolution_method_fails() {
let mut container = IocContainer::new();
container.bind_injectable::<TestInjectableOnlyService>();
container.build().unwrap();
let mut factory_container = IocContainer::new();
factory_container.bind::<TestService, TestService>();
factory_container.build().unwrap();
let service = container
.resolve_injectable::<TestInjectableOnlyService>()
.unwrap();
assert!(Arc::strong_count(&service) >= 1);
}
#[test]
fn test_service_descriptor_activation_strategy_debug() {
use crate::container::descriptor::ServiceDescriptor;
let factory_descriptor = ServiceDescriptor::bind::<TestService, TestService>().build();
let autowired_descriptor = ServiceDescriptor::autowired::<TestInjectableService>(vec![
ServiceId::of::<TestService>(),
]);
let factory_debug = format!("{:?}", factory_descriptor.activation_strategy);
let autowired_debug = format!("{:?}", autowired_descriptor.activation_strategy);
assert!(factory_debug.contains("Factory(<factory_fn>)"));
assert_eq!(autowired_debug, "AutoWired");
}
#[test]
fn test_clear_distinction_between_strategies() {
let mut container = IocContainer::new();
container
.bind::<TestService, TestService>()
.bind_injectable::<TestInjectableService>();
container.build().unwrap();
assert!(container.contains::<TestService>());
assert!(container.contains::<TestInjectableService>());
assert!(container.resolve::<TestService>().is_ok());
assert!(container
.resolve_injectable::<TestInjectableService>()
.is_ok());
let wrong_autowired_result = container.resolve::<TestInjectableService>();
assert!(wrong_autowired_result.is_err());
if let Err(CoreError::InvalidServiceDescriptor { message }) = wrong_autowired_result {
assert!(message.contains("is marked as auto-wired"));
assert!(message.contains("resolve_injectable"));
} else {
panic!("Expected InvalidServiceDescriptor error with auto-wiring message");
}
}
}