yadir 0.3.2

Yet Another Dependency Injection Registry for Rust
Documentation
//! # yadir
//!
//! `yadir` is yet another simple dependency injection registry for Rust.

pub mod core;
pub mod macros;

#[cfg(feature = "derive")]
extern crate yadir_derive;

#[cfg(feature = "derive")]
pub use yadir_derive::DIBuilder;

#[cfg(test)]
mod tests {
    use crate::core::contracts::DIBuilder;
    use crate::core::primitives::{DIManager, DIObj, Lifetime};
    use crate::{deps, let_deps};
    use async_trait::async_trait;
    use claim::assert_some;
    use dyn_clone::{clone_trait_object, DynClone};
    use uuid::Uuid;
    use yadir_derive::DIBuilder;

    clone_trait_object!(Printer);
    clone_trait_object!(Writer);

    trait Printer: Sync + Send + DynClone {
        fn print(&self) -> String;
    }

    trait Writer: Sync + Send + DynClone {
        fn write(&self) -> String;
    }

    #[derive(Clone, DIBuilder)]
    #[build_as(Box<dyn Printer>)]
    struct Bar;

    impl Printer for Bar {
        fn print(&self) -> String {
            "bar".to_string()
        }
    }

    #[derive(Clone, DIBuilder)]
    #[build_as(Box<dyn Writer>)]
    struct Baz;

    impl Writer for Baz {
        fn write(&self) -> String {
            "baz".to_string()
        }
    }

    #[derive(Clone, DIBuilder)]
    #[build_method("new")]
    struct Foo {
        id: Uuid,
        #[deps]
        printer: Box<dyn Printer>,
        #[deps]
        writer: Box<dyn Writer>,
    }

    impl Foo {
        fn new(printer: Box<dyn Printer>, writer: Box<dyn Writer>) -> Self {
            let id = Uuid::new_v4();
            Self {
                id,
                printer,
                writer,
            }
        }

        fn print(&self) -> String {
            format!("foo {} {}", self.printer.print(), self.writer.write())
        }

        fn id(&self) -> Uuid {
            self.id
        }
    }

    #[tokio::test]
    async fn test_di_manager_for_deps_transient_lifetimes() {
        let mut manager = DIManager::default();

        manager
            .register::<Bar>(Some(Lifetime::Transient))
            .await
            .register::<Baz>(Some(Lifetime::Transient))
            .await
            .register::<Foo>(Some(Lifetime::Transient))
            .await;

        let foo1 = manager.resolve::<Foo>().await;
        assert_some!(foo1.clone());

        let foo1 = foo1.unwrap().extract();
        assert_eq!(foo1.print(), "foo bar baz");

        let foo2 = manager.resolve::<Foo>().await;
        assert_some!(foo2.clone());

        let foo2 = foo2.unwrap().extract();
        assert_eq!(foo2.print(), "foo bar baz");

        assert_ne!(foo1.id(), foo2.id());
    }

    #[tokio::test]
    async fn test_di_manager_for_deps_singleton_lifetimes() {
        let mut manager = DIManager::default();

        manager
            .register::<Bar>(Some(Lifetime::Transient))
            .await
            .register::<Baz>(Some(Lifetime::Transient))
            .await
            .register::<Foo>(Some(Lifetime::Singleton))
            .await;

        let foo1 = manager.resolve::<Foo>().await;
        assert_some!(foo1.clone());

        let foo1 = foo1.unwrap().extract();
        assert_eq!(foo1.print(), "foo bar baz");

        let foo2 = manager.resolve::<Foo>().await;
        assert_some!(foo2.clone());

        let foo2 = foo2.unwrap().extract();
        assert_eq!(foo2.print(), "foo bar baz");

        assert_eq!(foo1.id(), foo2.id());
    }

    #[tokio::test]
    async fn test_di_manager_for_not_resolving_unregistered_deps() {
        let mut manager = DIManager::default();

        manager
            .register::<Baz>(Some(Lifetime::Transient))
            .await
            .register::<Bar>(Some(Lifetime::Transient))
            .await;

        let foo = manager.resolve::<Foo>().await;
        assert!(foo.is_none());
    }
}