I have this rust code where I am trying to implement observability. And, in my closure add_foo_listener
I simply update the called
variable and then assert it it's called.
This code compiles, and the closure is invoked, as is evidenced by the println
, but the called
variable doesn't stick. Everything I read says I should be using FnMut
which, I believe I am. But, I don't understand why this boolean isn't being updated
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
struct Foo {
baz: u32
}
struct Holder {
pub foo_observers: Vec<Box<dyn FnMut(Foo)>>,
}
impl Holder {
pub fn add_foo_listener<CB: 'static + FnMut(Foo) + FnMut(Foo)>(&mut self, on_foo: CB) -> &mut Self {
self.foo_observers.push(Box::new(on_foo));
self
}
pub fn notify_foo_event(&mut self, foo: Foo) -> &mut Self {
self.foo_observers
.iter_mut()
.for_each(|notify| notify(foo.clone()));
self
}
}
#[test]
fn test_foo() -> Result<(), String> {
let mut holder = Holder{
foo_observers: Vec::new()
};
let mut called: bool = false;
let foo = Foo{
baz : 10
};
holder.add_foo_listener( move |f: Foo| {
println!("Listener called");
called = true;
}).notify_foo_event(foo);
assert!(called); // called is still false
Ok(())
}
Output:
---- notifier::test::test_foo stdout ----
Listener called
thread 'notifier::test::test_foo' panicked at 'assertion failed: called', foo.rs
assert!(called);
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace