单元测试里的怎么用mock函数替换被测试函数里调用的函数?

我有一段代码的逻辑大概是这样的,在utils模块的generate_id里调用了random模块的random_odd_int生成一个ID。

我现在想要想一个测试方法只测试utils模块里generate_id是否正确,random_odd_int函数已经有专门的测试方法了。我该怎么来写这个测试方法在执行单元测试的时候,generate_id调用random_odd_int时调用的是random_odd_int的mock方法每次都返回一个固定值?

我尝试了mockall这个库,但没有成功,mockall设置random_odd_int的mock方法只有在测试方法里调用才起作用,generate_id函数里调用的random_odd_int还是random模块里的方法。

pub mod utils {
    use super::random::random_odd_int;

    pub fn generate_id() -> String {
        // 在这里调用random里的random_odd_int
        let seed = random_odd_int();
        format!("{:010}", seed)
    }
}


#[cfg(test)]
mod tests {
    use crate::utils::utils::generate_id;

    #[test]
    fn test_generate_id() {
        let excepted = "newid9091";
        // 在调用generate_id之前,我要怎样使用mock才能让random_odd_int返回固定值
        let actual = generate_id();
        assert_eq!(actual, excepted.to_string());
    }
}
讨论数量: 1
Oraoto

可以用 mockall_double

pub mod random {
    pub fn random_odd_int() -> i32 {
        // REAL implementation
        42
    }
}

// 实现一个 module 替换掉 random
// 如果你用 mockall 就在上面的 random 加 automock,更加灵活,可以在测试里改返回值
pub mod mock_random {
    pub fn random_odd_int() -> i32 {
        // mock implementation
        1
    }
}

pub mod utils {
    use mockall_double::double;

    // 在 #[cfg(test)] 里,这里会替换成 use super::mock_random;
    #[double]
    use super::random;

    pub fn generate_id() -> String {
        let seed = random::random_odd_int();
        format!("{}", seed)
    }
}


#[cfg(test)]
mod tests {

    use crate::utils::utils::generate_id;

    #[test]
    fn test_generate_id() {
        let excepted = "1";
        let actual = generate_id();
        assert_eq!(actual, excepted.to_string());
    }
}

结合 mockall 就是这样:

use mockall::*;

#[automock]
pub mod random {
    pub fn random_odd_int() -> i32 {
        // REAL implementation
        42
    }
}

pub mod utils {
    use mockall_double::double;

    #[double]
    use super::random;

    pub fn generate_id() -> String {
        let seed = random::random_odd_int();
        format!("{}", seed)
    }
}


#[cfg(test)]
mod tests {

    use crate::utils::utils::generate_id;

    #[test]
    fn test_generate_id() {
        let ctx = super::mock_random::random_odd_int_context();
        ctx.expect().return_const(1);

        let excepted = "1";
        let actual = generate_id();
        assert_eq!(actual, excepted.to_string());
    }
}
3个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!