Search code examples
unit-testingrust

Mocking functions in rust


Is there a way to mock regular functions in rust?

Consider the following code:

fn main() {
    println!("{}", foo());
}

fn get_user_input() -> u8 {
    // Placeholder for some unknown value
    42
}

fn foo() -> u8 {
    get_user_input()
}

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

        get_user_input = || 12u8;

        assert_eq!(foo(), 12u8);
    }
}

I would like to unit test foo() without having to rely on the output of get_user_input(). I obviously cannot overwrite get_user_input() like I tried in the example code.

I have only found ways to mock structs, traits and modules but nothing about mocking regular free functions. Am I missing something?

Edit: I have looked primarily at the mockall crate.


Solution

  • You could use cfg:

    #[cfg(not(test))]
    fn get_user_input() -> u8 {
        // Placeholder for some unknown value
        42
    }
    
    #[cfg(test)]
    fn get_user_input() -> u8 {
        12
    }
    

    playground

    Or dependency injection:

    pub fn main() {
        println!("{}", foo(get_user_input));
    }
    
    fn get_user_input() -> u8 {
        // Placeholder for some unknown value
        42
    }
    
    fn foo(get_user_input_: impl Fn() -> u8) -> u8 {
        get_user_input_()
    }
    
    #[cfg(test)]
    mod tests {
        #[test]
        fn test_foo() {
            use super::*;
            
            let get_user_input = || 12u8;
    
            assert_eq!(foo(get_user_input), 12u8);
        }
    }
    

    playgound