How to check if a function has been called in Rust?

后端 未结 2 1105
孤城傲影
孤城傲影 2021-01-14 18:54

I have a function as follows

pub fn registration(student_id: &T::StudentId, registrar: &T::RegistrarID) {
    // More code here.
    if num_of_studen         


        
2条回答
  •  再見小時候
    2021-01-14 19:47

    Strong opinion alert: you are doing your testing wrong. This is on the same level as "how do I test a private method". You shouldn't care about the implementation of registration to this level of detail.

    That being said, if it's actually important to know which if branch is taken, then use dependency injection:

    fn registration(mut registration: impl Registration, registrar: i32) {
        let num_of_students = 0;
        let student_limit = 0;
    
        if num_of_students < student_limit {
            registration.function_one(registrar, num_of_students);
        } else {
            registration.function_two(num_of_students);
        }
    }
    
    trait Registration {
        fn function_one(&mut self, registrar: i32, num_of_students: i32);
        fn function_two(&mut self, num_of_students: i32);
    }
    
    impl Registration for &'_ mut R {
        fn function_one(&mut self, registrar: i32, num_of_students: i32) {
            (**self).function_one(registrar, num_of_students)
        }
        fn function_two(&mut self, num_of_students: i32) {
            (**self).function_two(num_of_students)
        }
    }
    
    /*
    // An example implementation for production
    struct DatabaseRegistration;
    
    impl Registration for DatabaseRegistration {
        fn function_one(&mut self, registrar: i32, num_of_students: i32) {
            eprintln!("Do DB work: {}, {}", registrar, num_of_students)
        }
        fn function_two(&mut self, num_of_students: i32) {
            eprintln!("Do DB work: {}", num_of_students)
        }
    }
    */
    
    #[cfg(test)]
    mod test {
        use super::*;
    
        #[derive(Debug, Copy, Clone, Default)]
        struct TestRegistration {
            calls_to_one: usize,
            calls_to_two: usize,
        }
    
        impl Registration for TestRegistration {
            fn function_one(&mut self, _: i32, _: i32) {
                self.calls_to_one += 1;
            }
            fn function_two(&mut self, _: i32) {
                self.calls_to_two += 1;
            }
        }
    
        #[test]
        fn calls_the_right_one() {
            let mut reg = TestRegistration::default();
            registration(&mut reg, 42);
            assert_eq!(1, reg.calls_to_two)
        }
    }
    

    Once you have done this, then you can see that registration calls the appropriate trait function (as shown in the example test).

    This prevents your production code from having test-specific detritus strewn about while also giving you the ability to be more flexible and test more cases rapidly.

    See also:

    • How can I test stdin and stdout?
    • How to mock external dependencies in tests?
    • Is there a cleaner way to test functions that use functions that require user input in Rust?
    • How can I test Rust methods that depend on environment variables?
    • Is there a way of detecting whether code is being called from tests in Rust?

提交回复
热议问题