Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: support for const generics in mock! and automock #568

Open
korbinian-maier-bl opened this issue Apr 16, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@korbinian-maier-bl
Copy link

Hi,
first of all, we this crate extensively, it makes testing and mocking easy and accessible. Thanks for that!

We now hit one limitation though: const generics are not yet supported as the macro tells us: message: #automock does not yet support generic constants.

For instance, if you have a struct with an array

struct Status<const N: usize> {
    elements: [u32; N],
}

neither automock nor mock! for a Status<const N: usize> works as expected.

Is the support of const generics planned or are there any major roadblocks preventing the implementation?

If it's just a matter of resources I'd like to try and implement this even (if you'd be willing to give some guidance of course).

@asomers
Copy link
Owner

asomers commented Apr 16, 2024

More fundamentally, mocking fields isn't even possible. How would you propose accessing the mock object's elements array?

@asomers asomers added the enhancement New feature or request label Apr 16, 2024
@korbinian-maier-bl
Copy link
Author

Yeah, sorry. That example doesn't make sense. While trying to come up with a simple thing I got confused.

Next try: the trait FixedContainer can be mocked but the Container trait can't be.

// #[cfg_attr(test, mockall::automock)] // Macro panics
pub trait Container<const N: usize> {
    fn times(&mut self, m: [u32; N]);
    fn add(&mut self, m: [u32; N]);
}

#[cfg_attr(test, mockall::automock)]
pub trait FixedContainer {
    fn times(&mut self, m: [u32; 3]);
    fn add(&mut self, m: [u32; 3]);
}

pub struct Outer<T: FixedContainer> {
    container: T,
}

impl<T: FixedContainer> Outer<T> {
    pub fn new(container: T) -> Self {
        Self { container }
    }

    pub fn arithmetic(&mut self, number: u32, add: bool) {
        if add {
            self.container.add([number; 3]);
        } else {
            self.container.times([number; 3]);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn fixed_container() {
        let mut mocked = MockFixedContainer::new();
        mocked.expect_add().once().returning(|_| ());
        mocked.expect_times().once().returning(|_| ());

        let mut outer = Outer::new(mocked);
        outer.arithmetic(1, true);
        outer.arithmetic(1, false);
    }
}

Does that make more sense? Is there any fundamental reason why this can't be supported?

@asomers
Copy link
Owner

asomers commented Apr 16, 2024

I think it could be done. But just as you must for associated types. you'd have to tell automock what value of N to use.

@korbinian-maier-bl
Copy link
Author

So something like #[automock(const N=5;)] or whatever keyword you'd choose for the const generic, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants