How to unit test functions without return type?

Hi,

i'm fairly new to Rust and I like the language so far.
I often stumble on software design problems, due to lifetime or ownership.
But so far, I eventually found a way to write things in a more "rusty" fashion.

However, I didn't find out how to unit test functions without return type.

Take following use case for example:

pub trait TaskWorker {
    fn is_applicable(&self, input: &String) -> bool;
    fn execute(&self, input: &String);
}

pub struct TaskWorkers {
    workers: Vec<Box<dyn TaskWorker>>
}

impl TaskWorkers {
    pub fn init() -> TaskWorkers {
        TaskWorkers {
            workers: vec![
                Box::from(WorkerA {}),
                Box::from(WorkerB {})
            ]
        }
    }

    fn execute(&self,  item: &String) {
        let worker = self.workers.iter()
            .find(|w| w.is_applicable(item))
            .expect("No Worker found!");

        worker.execute(item);
    }
}

I would like to unit test the execute function.
It should select the first worker that is applicable for the given input,
and then use the worker's execute function to process it.

My unit test, that I'd tried to write, looks like this:

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

    struct MockWorker {
        check_string: String
    }

    impl TaskWorker for MockWorker {
        fn is_applicable(&self, input: &String) -> bool {
            self.check_string.eq(input)
        }

        fn execute(&self, input: &String) {
            // ???
        }
    }

    #[test]
    fn it_should_find_and_execute_correct_worker() {
        let workerA = MockWorker {check_string: "A"};
        let workerB = MockWorker {check_string: "B"};

        let workers = TaskWorkers {workers: vec![Box::of(workerA), Box::of(workerB)]};
        workers.execute(&String::from("B"));

        // How do I check that workerB.execute has been called, and not workerA.execute?
    }

}

I can't mutate the inner state of a MockWorker instance, since TaskWorker.execute has only a borrowed self.
When I try to use mutable static variables to record an execute run, it seems not to work without unsafe.

I am probably missing something obvious here, but after searching on google and reading the Rust Book up and down, I'm all out of ideas. Is there a "rusty" kind of way to do this?

You can use the Cell type in one of the fields to allow modifying that field from execute.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.