如何检查是否一个功能拉斯特被称为?

问题描述 投票:1回答:2

我有一个函数如下

pub fn registration(student_id: &T::StudentId, registrar: &T::RegistrarID) {
    // More code here.
    if num_of_students < student_limit {
        Self::function_one(&registrar, &num_of_students);
    } else {
        Self::function_two(&num_of_students);
    }
}

在单元测试中,我打算检查function_onefunction_two是否被调用。

#[test]
fn registration_more_students_should_call_functon_one() {
    with_test_data(
        &mut TestBuilder::default().num_of_students(1000).build(),
        || {
            //assert_called!(module_name::registration("TV:009", "DF-000-09"));
        },
    );
}

如何测试如果一个函数在锈叫什么名字?

unit-testing rust
2个回答
4
投票

这是在多个地方使用#[cfg(test)]一个天真的尝试:

struct Registration {
    students: Vec<String>,
    #[cfg(test)]
    function_1_called: bool,
}

impl Registration {
    fn new() -> Self {
        Registration {
            students: Vec::new(),
            #[cfg(test)]
            function_1_called: false,
        }
    }

    fn function_1(&mut self, students: Vec<String>) {
        self.students.extend(students);
        #[cfg(test)]
        {
            self.function_1_called = true;
        }
    }

    fn function_2(&mut self, students: Vec<String>) {}

    fn f(&mut self, students: Vec<String>) {
        if students.len() < 100 {
            self.function_1(students);
        } else {
            self.function_2(students);
        }
    }
}

fn main() {
    println!("Hello, world!");
    let r = Registration::new();
    // won't compile during `run`:
    // println!("{}", r.function_1_called);
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_f() {
        let mut r = Registration::new();
        r.function_1(vec!["Alice".to_string(), "Bob".to_string()]);
        assert!(r.function_1_called);
    }
}

该代码是松散的基础上,你所提供的片段。有一个Registration结构保存登记学生学生姓名,两种方法function_1function_2的列表,以及ffunction_1之间的选择取决于Ø有多少学生有一个功能function_2

在测试过程中,Registration编译时附加的布尔变量function_1_called。此变量只设置如果function_1被调用(即这是否代码块还标有#[cfg(test)])。

在组合,这使得在测试过程中提供额外的布尔标志,这样就可以使类似以下声明:

assert!(r.function_1_called);

显然,这可以为结构较单一布尔标志更为复杂的工作(这并不都意味着你应该真正做到这一点)。

我不能在这是否是地道的铁锈或发表评论。整个安装感觉好像应该看中宏背后隐藏的,因此,如果这种风格的测试鲁斯特用于在所有的,应该已经是提供这些(或类似)宏板条箱。


8
投票

强大的舆论警告:你在做你的测试错误。这是在同一水平上的“我怎么测试的私有方法”。你不应该在乎registration的实施,这种详细程度。

话虽这么说,如果知道哪个if分支,然后使用依赖注入实际上是很重要的:

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<R: Registration> 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)
    }
}

一旦你做到了这一点,那么你就可以看到registration调用适当的特征函数(如示例所示的测试)。

这可以防止你的生产代码具有特定的测试碎屑四散,同时也让你更加灵活,快速地测试更多案件的能力。

也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.