mry_macros 0.14.0

Macro crate for mry, a simple but powerful mocking library that supports struct, trait, and function.
Documentation
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};
use syn::ItemFn;

use crate::{attrs::MryAttr, method};

pub(crate) fn transform(mry_attr: &MryAttr, input: ItemFn) -> TokenStream {
    let (original, mock) = method::transform(
        mry_attr,
        quote![mry::get_static_mocks()],
        Default::default(),
        "",
        quote![mry::static_record_call_and_find_mock_output],
        Some(&input.vis),
        &input.attrs,
        &input.sig,
        &input
            .block
            .stmts
            .iter()
            .fold(TokenStream::default(), |mut stream, item| {
                item.to_tokens(&mut stream);
                stream
            }),
        false,
    );

    quote! {
        #original
        #mock
    }
}

#[cfg(test)]
mod test {
    use pretty_assertions::assert_eq;
    use syn::parse2;

    use super::*;

    #[test]
    fn add_mry_object() {
        let input: ItemFn = parse2(quote! {
            fn meow(count: usize) -> String {
                "meow".repeat(count)
            }
        })
        .unwrap();

        assert_eq!(
            transform(&MryAttr::default(), input).to_string(),
            quote! {
                #[cfg_attr(debug_assertions, track_caller)]
                fn meow(count: usize) -> String {
                    #[cfg(debug_assertions)]
                    if let Some(out) = mry::static_record_call_and_find_mock_output::<_, String>(std::any::Any::type_id(&meow), "meow", (<usize>::clone(&count),)) {
                        return out;
                    }
                    (move || {
                        "meow".repeat(count)
                    })()
                }

                #[cfg(debug_assertions)]
                #[must_use]
                pub fn mock_meow(count: impl Into<mry::ArgMatcher<usize>>) -> mry::MockLocator<(usize,), String, String, mry::Behavior1<(usize,), String> > {
                    mry::MockLocator::new(
                        mry::get_static_mocks(),
                        std::any::Any::type_id(&meow),
                        "meow",
                        (count.into(),).into(),
                        std::convert::identity,
                    )
                }
            }
            .to_string()
        );
    }

    #[test]
    fn add_allow_non_snake_case() {
        let input: ItemFn = parse2(quote! {
            fn _meow(count: usize) -> String {
                "meow".repeat(count)
            }
        })
        .unwrap();

        assert_eq!(
            transform(&MryAttr::default(), input).to_string(),
            quote! {
                #[cfg_attr(debug_assertions, track_caller)]
                fn _meow(count: usize) -> String {
                    #[cfg(debug_assertions)]
                    if let Some(out) = mry::static_record_call_and_find_mock_output::<_, String>(std::any::Any::type_id(&_meow), "_meow", (<usize>::clone(&count),)) {
                        return out;
                    }
                    (move || {
                        "meow".repeat(count)
                    })()
                }

                #[cfg(debug_assertions)]
                #[allow(non_snake_case)]
                #[must_use]
                pub fn mock__meow(count: impl Into<mry::ArgMatcher<usize>>) -> mry::MockLocator<(usize,), String, String, mry::Behavior1<(usize,), String> > {
                    mry::MockLocator::new(
                        mry::get_static_mocks(),
                        std::any::Any::type_id(&_meow),
                        "_meow",
                        (count.into(),).into(),
                        std::convert::identity,
                    )
                }
            }
            .to_string()
        );
    }
}