I've started extracting functions to traits in order to provide a different implementation during testing. For example:
pub trait Broadcast {
fn broadcast_message(&self, message: &str);
}
pub struct PrintLnBroadcast {}
impl Broadcast for PrintLnBroadcast {
fn broadcast_message(&self, message: &str) {
println!("{}", message);
}
}
This works fine, but when I want to add a test implementation of Broadcast, it often requires making the self parameter mutable.
Continuing with the example:
struct AccumulatingBroadcast {
messages: Vec<Box<str>>
}
impl Broadcast for AccumulatingBroadcast {
fn broadcast_message(&mut self, message: &str) {
self.messages.push(Box::from(message));
}
}
The AccumulatingBroadcast struct's contents can then be inspected to verify the right broadcasts were called.
With this approach, the mutability of the self parameter becomes infectious and requires changing the function in the trait too, and thus also in the production implementation.
Is there a better way to do this than having this explosion of mutability? I don't want test requirements to decrease the quality of production code.
I'm aware of crates like mockall, but I'm wondering if there's a way to do this in standard Rust for learning purposes.