How to test a method that takes `&mut self` as an argument?

Stripped to the bone, my program is object-oriented and looks like that:

struct MyObject {
    data: i32,
}

impl MyObject {
    fn a_method(&mut self) {
        self.data += 2
    }
}

And I want to test a_method, so I write :

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

    #[test]
    fn the_method_works() {
        assert_eq!(MyObject { data: 4 }, a_method(MyObject { data: 2 }))
    }

Obviously this doesn't work because the expression on the right returns () and not a n instance of MyObject.

I have looked around and could not find an answer, so clearly I am missing something.

You can create an instance of MyObject, apply the method and then do the assert separately:

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

    #[test]
    fn the_method_works() {
        let mut obj = MyObject {data: 2};
        obj.a_method();
        assert_eq!(MyObject { data: 4 }, obj)
    }
}
1 Like

Why couldn't I think of that myself? Thank you very much.

2 Likes

The apply crate has a trait for this — apply::Also:

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

    #[test]
    fn the_method_works() {
        assert_eq!(MyObject { data: 2 }.also(MyObject::a_method), MyObject { data: 4 });
    }
}

(Admittedly, also is perplexing name.)

Nice! I guess this gets usefull when dealing with a ton of methods.

also is an okay keyword considering you may want to pile up several methods on top of each other, like you'd order several things off a menu in the restaurant. "I'll have an iterator with soda, also an in-place sorting beer, also a huge plate of &mut self fries."

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.