Automock - crate for mocking anything

Hi! I'd like to share a project I've been working on in my free time for the past year.
It's a crate for mocking functions, traits and structs.

https://crates.io/crates/automock

#[automock::mock]
trait Trait {
    fn work(&self, v: i32) -> i32;
}

#[test]
fn test() {
    // Arrange
    let mut mock = TraitMock::new();
    mock.setup().work(1).returns_once(2);
    
    // Act
    let result = mock.work(1);
    
    // Assert
    assert_eq!(result, 2);
    mock.verify_calls();
}

It already covers almost all of mockall and faux crates features (two of the most widely used crates for mocking), so I'll focus on some of its advantages in this post:

  1. Partial mocking - you can configure mocked function to use its original implementation in certain scenarios:
    #[automock::mock]
    trait Trait {
        fn work(&self, v: i32) -> i32 {
            4  // base implementation
        }
    }
    
    #[test]
    fn main() {
        // Arrange
        let mut mock = TraitMock::new();
        mock.setup()
            .work(1).returns_once(2)
            .work(3).call_base();
    
        // Act
        let first  = mock.work(1);
        let second = mock.work(3); // uses base implementation
    
        // Assert
        assert_eq!(first,  2);
        assert_eq!(second, 4);
        mock.verify_calls();
    }
    
  2. Static functions mocking - any static function can be mocked, whether it's standalone or associated function:
    #[automock::mock]
    fn work(v: i32) -> i32 { v }
    
    #[automock::mock]
    trait Trait {
        fn work(v: i32) -> i32;
    }
    
    fn use_trait<T: Trait>(v: i32) -> i32 { T::work(v) }
    
    #[test]
    fn test() {
        // Arrange
        work::setup(1).returns_once(2);
        TraitMock::static_setup().work(3).returns_once(4);
    
        // Act
        let first  = work(1);
        let second = use_trait::<TraitMock>(3);
    
        // Assert
        assert_eq!(first, 2);
        assert_eq!(second, 4);
        work::verify_calls();
        TraitMock::verify_static_calls();
    }
    
  3. A single #[mock] attribute for everything - you can apply it to traits, structs, struct implementations, trait on struct implementations or static functions. No need for mock!, #[concretize], #[double], #[faux::create]or #[faux::methods] attributes.
  4. Better generics: support for lifetimes and default generic values.
    Here's an example of monstrous trait implementation that it can mock
    #[mock]
    impl<'a, 'b: 'a, T1: Clone> Trait<'a, 'b, T1> for Struct<'a, 'b, T1> {
        fn work<'c, 'd: 'a, T2: Clone>(
            &self,
            a: &'a i32,
            b: &'b i32,
            c: &'c i32,
            d: &'d i32,
            axb: &'a &'_ &'b i32,
            cxd: &'c &&'d i32,
            abxbax: &'a &'b &&'b &'a &i32,
            cdxdcx: &'c &'d &&'d &'c &i32,
            abcd: &'a &'b &'c &'d i32,
            xaxbxcxdx: &&'a &&'b &&'c &&'d &i32,
            data: Data<
                'a,
                'b,
                &&i32,
                &&'a &&'b &[&'c &&'b &Data<'c, 'a, &'_ &&'c &i32, Vec<&'d &'b &()>>],
            >,
            t1: T1,
            t1_ref: &T1,
            xaxbxcxdx_t1_ref: &&'a &&'b &&'c &&'d &T1,
            t2: T2,
            t2_ref: &T2,
            xaxbxcxdx_t2_ref: &&'a &&'b &&'c &&'d &T2,
            xapx: &&'a *const &i32,
        ) -> &&'a &&'a &&'b &&'b &&'c &&'c &&'d &&'d &i32 {
            Struct::<'a, 'b, T1>::work(
                self,
                a,
                b,
                c,
                d,
                axb,
                cxd,
                abxbax,
                cdxdcx,
                abcd,
                xaxbxcxdx,
                data,
                t1,
                t1_ref,
                xaxbxcxdx_t1_ref,
                t2,
                t2_ref,
                xaxbxcxdx_t2_ref,
                xapx,
            )
        }
    }
    

    Full example: automock/automock/tests/reference_tests.rs at af3eb2f069dc9efd33e8bbdc94442f0e0d2585e1 · alordash/automock · GitHub

You can see full list of features in the crate's documentation: automock - Rust

Source code: GitHub - alordash/automock: Universal mocks in Rust. · GitHub