diff options
| author | HampusM <hampus@hampusmat.com> | 2023-08-16 22:35:47 +0200 | 
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2023-08-16 22:36:09 +0200 | 
| commit | 800e164a83388aa5ca7675f8031b0f0d7c6b6051 (patch) | |
| tree | 744cbab2db5ff7ca4edb3713ceabf24d79620df0 | |
| parent | 595806824d41c696b660f40c01914a24e9618f1d (diff) | |
test: make the prevent-circular example an integration test
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | examples/prevent-circular/main.rs | 52 | ||||
| -rw-r--r-- | tests/prevent_circular.rs | 94 | 
3 files changed, 94 insertions, 56 deletions
@@ -35,10 +35,6 @@ required-features = ["async", "factory"]  name = "async-factory"  required-features = ["async", "factory"] -[[example]] -name = "prevent-circular" -required-features = ["prevent-circular"] -  [dependencies]  syrette_macros = { path = "./macros", version = "0.4.2" }  linkme = "0.3.0" diff --git a/examples/prevent-circular/main.rs b/examples/prevent-circular/main.rs deleted file mode 100644 index c690a9c..0000000 --- a/examples/prevent-circular/main.rs +++ /dev/null @@ -1,52 +0,0 @@ -//! Example demonstrating the prevention of circular dependencies. -//! -//! Having circular dependencies is generally bad practice and is detected by Syrette when -//! the `prevent-circular` feature is enabled. -#![deny(clippy::all)] -#![deny(clippy::pedantic)] -#![allow(clippy::disallowed_names)] - -use syrette::di_container::blocking::prelude::*; -use syrette::injectable; -use syrette::ptr::TransientPtr; - -struct Foo -{ -    _bar: TransientPtr<Bar>, -} - -#[injectable] -impl Foo -{ -    fn new(bar: TransientPtr<Bar>) -> Self -    { -        Self { _bar: bar } -    } -} - -struct Bar -{ -    _foo: TransientPtr<Foo>, -} - -#[injectable] -impl Bar -{ -    fn new(foo: TransientPtr<Foo>) -> Self -    { -        Self { _foo: foo } -    } -} - -fn main() -> Result<(), anyhow::Error> -{ -    let mut di_container = DIContainer::new(); - -    di_container.bind::<Foo>().to::<Foo>()?; -    di_container.bind::<Bar>().to::<Bar>()?; - -    // The following won't work. Err will be returned. -    let _foo = di_container.get::<Foo>()?.transient()?; - -    Ok(()) -} diff --git a/tests/prevent_circular.rs b/tests/prevent_circular.rs new file mode 100644 index 0000000..4b95dea --- /dev/null +++ b/tests/prevent_circular.rs @@ -0,0 +1,94 @@ +#![deny(clippy::all, clippy::pedantic)] +#![allow(clippy::disallowed_names)] + +use syrette::di_container::blocking::prelude::*; +use syrette::errors::di_container::DIContainerError; +use syrette::errors::injectable::InjectableError; +use syrette::injectable; +use syrette::ptr::TransientPtr; + +#[derive(Debug)] +struct Foo +{ +    _bar: TransientPtr<Bar>, +} + +#[injectable] +impl Foo +{ +    fn new(bar: TransientPtr<Bar>) -> Self +    { +        Self { _bar: bar } +    } +} + +#[derive(Debug)] +struct Bar +{ +    _foo: TransientPtr<Foo>, +} + +#[injectable] +impl Bar +{ +    fn new(foo: TransientPtr<Foo>) -> Self +    { +        Self { _foo: foo } +    } +} + +macro_rules! assert_match { +    ($target: expr, $pattern: pat => $expr: expr) => {{ +        let target = $target; + +        // Not all pattern variables will be used here +        #[allow(unused_variables)] +        { +            assert!(matches!(&target, $pattern)); +        } + +        match target { +            $pattern => $expr, +            _ => { +                unreachable!(); +            } +        } +    }}; +} + +#[test] +fn prevent_circular_works() +{ +    let mut di_container = DIContainer::new(); + +    di_container.bind::<Foo>().to::<Foo>().expect("Expected Ok"); +    di_container.bind::<Bar>().to::<Bar>().expect("Expected Ok"); + +    let err = di_container.get::<Foo>().expect_err("Expected Err"); + +    let container_err_a = assert_match!( +        err, +        DIContainerError::BindingResolveFailed { +            reason: InjectableError::ResolveFailed { reason, affected: _ }, +            interface: _ +        } => *reason +    ); + +    let container_err_b = assert_match!( +        container_err_a, +        DIContainerError::BindingResolveFailed { +            reason: InjectableError::ResolveFailed { reason, affected: _ }, +            interface: _ +        } => *reason +    ); + +    assert!(matches!( +        container_err_b, +        DIContainerError::BindingResolveFailed { +            reason: InjectableError::DetectedCircular { +                dependency_history: _ +            }, +            interface: _ +        } +    )); +}  | 
