audunhalland / unimock

A versatile and developer-friendly trait mocking library
MIT License
71 stars 3 forks source link

Example to use mutates with a non-primitive Type #37

Closed wackazong closed 8 months ago

wackazong commented 8 months ago

I would like to use the mutates functionality with a struct reference. But I cannot get it to work, inside of the closure the mutable reference does not have a type. Can you give an example for mutates with a non-primitive type?

audunhalland commented 8 months ago

Hi, can you make a small code example that demonstrates the issue?

audunhalland commented 8 months ago

An example of something that works can be found in https://docs.rs/unimock/0.5.7/src/unimock/mock/core.rs.html#10, the mock implementation for core::fmt::Display.

The f parameter in fmt is &mut core::fmt::Formatter, and can be used like this:

            DisplayMock::fmt
                .next_call(matching!())
                .mutates(|f, _| write!(f, "u"))

The test for this is in https://github.com/audunhalland/unimock/blob/e9430092357031567c80b0ba17ea24e6bafba7ec/tests/it/std.rs#L14.

wackazong commented 8 months ago

Ok, my entrait function has a generic type paramater, that seems to cause the issue. As soon as I introduce that, the error appears.

This does not compile, as soon as I remove the generic parameter, it compiles without issues.

trait MyTrait {}

struct MyStruct;

impl MyTrait for MyStruct {}

struct MyFoo {
    baz: u32,
}

#[entrait::entrait(pub MyEntrait, no_deps, mock_api=MyEntraitTest)]
pub fn my_entrait<T>(nasty: T, foo: &mut MyFoo)
where
    T: MyTrait,
{
}

#[test]
fn test_my_entrait() {
    let mocked_deps = Unimock::new(
        MyEntraitTest
            .with_types::<MyStruct>()
            .some_call(matching!(_))
            .mutates(|m, _| {
                m.baz = 34;
            }),
    );
}

The error is

no field `baz` on type `&mut <impl unimock::MockFn<Inputs = (methods::execute::router::tests::MyStruct, unimock::PhantomMut<&'__i methods::execute::router::tests::MyFoo>), Response = unimock::output::Owned<()>> as unimock::MockFn>::Mutation<'_>`

I also cannot replace T with &mut impl MyTrait because of https://github.com/audunhalland/entrait/issues/27.

audunhalland commented 8 months ago

Thanks! https://github.com/audunhalland/unimock/pull/38 should fix that.

edit: 0.5.8 released with this fix!