rust 模拟,预先设置后续方法调用返回

xriantvc  于 2023-04-06  发布在  其他
关注(0)|答案(1)|浏览(88)

我尝试用mockall crate测试trait的功能。
问题是我找不到允许预定义一些后续方法返回的crate功能。
这里有一个设置来说明,有两个crate,一个调用另一个的所有方法:

pub trait Trait1 {
    fn func1(&self) -> Result<(), SomeError>;
    fn func2(&self) -> Result<(), SomeError>;
}

pub trait Trait2: Trait1 {
    // calls func1 and func2
    fn funcX(&self) -> Result<(), SomeError> {
        self.func1()?; // return OK only if both funcs return OK
        self.func2()?;
        Ok(())
    }
}
pub enum SomeError {
    Err,
}
mock! {
    TestMe {}
    impl Trait1 for TestMe{
        fn func1(&self) -> Result<(), SomeError>;
        fn func2(&self) -> Result<(), SomeError>;

    }
    impl Trait2 for TestMe{
        fn funcX(&self) -> Result<(), SomeError>;
    }
}

假设我想测试一下如果我得到func1并返回Error会是什么情况,即在这种情况下,我希望funcX返回Error。***问题是,我找不到任何预定义的可能性,func1返回Error。***下面是一个例子。

let mut mock_moving = Box::new(MockTestMe::new());
mock_moving
    .setup(func1 returns SomeError::Err) // <--- ????? should be like this
    .expect_funcX() // we expect this function to be called
    .times(1)
    .returning(move || SomeError::Err); //because func1 returns Error
mock_moving.funcX(); // calling funcX, expect it to call func1 and func2

我唯一允许写的东西是这样的:

let mut mock_moving = Box::new(MockTestMe::new());
mock_moving
    .expect_funcX() // we expect this function to be called
    .times(1)
    .returning(move || SomeError::Err);
mock_moving.funcX(); // of course it returns Error! I pre-defined its output, useless!

我想知道是否有一些方法可以提前设置trait方法的返回,这样我就可以独立于父trait方法的实现来测试trait。

e0bqpujr

e0bqpujr1#

我自己找到了解决方案。问题是我不明白嘲笑内部是如何工作的。下面是我自己的答案的解决方案:

pub trait Trait1 {
    fn func1(&self) -> Result<(), SomeError>;
    fn func2(&self) -> Result<(), SomeError>;
}

pub trait Trait2: Trait1 {
    // calls func1 and func2
    fn funcX(&self) -> Result<(), SomeError> {
        self.func1()?; // return OK only if both funcs return OK
        self.func2()?;
        Ok(())
    }
}
pub enum SomeError {
    Err,
}
mock! {
    TestMe {}
    impl Trait1 for TestMe{
        fn func1(&self) -> Result<(), SomeError>; // mocking this
        fn func2(&self) -> Result<(), SomeError>; // mocking this

    }
    impl Trait2 for TestMe{
        //should be left default because we testing this call
    }
}

试验台:

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

    #[test]
    fn sometest() {
        let mut mock_moving = Box::new(MockTestMe::new());
        mock_moving
            .expect_func1() 
            .times(1)
            .returning(|| Err(SomeError::Err)); // set output to func1
     mock_moving
            .expect_func2() 
            .times(1)
            .returning(|| Ok(()); //set output to func2

        assert!(mock_moving.funcX().is_err()); // call funcX that calls func1 and func2 with 
                                               //provided output

    }
}

相关问题