#mocking #tdd #test

simulacrum

使用稳定 Rust 手动创建模拟对象的极简库

7 个版本

使用旧的 Rust 2015

0.3.1 2018 年 3 月 29 日
0.3.0 2018 年 3 月 28 日
0.2.2 2018 年 3 月 25 日
0.2.0 2018 年 1 月 9 日
0.1.0 2017 年 12 月 17 日

#519 in 测试

23 每月下载量
用于 mdbook-plantuml

MIT 许可证

77KB
1.5K SLoC

Simulacrum Docs Crates.io

使用稳定 Rust 手动创建模拟对象的极简库。

要安装,将以下行添加到您的 Cargo.toml 文件中

[dependencies]
simulacrum = "0.3.0"

请注意,此 crate 尚未达到 1.0 版本,因此 API 可能会在版本之间发生重大变化。

使用模拟对象

Simulacrum 模拟对象提供了一致的用户界面,具有调用次数、参数匹配、返回值和通过可变引用修改参数的功能。

// Create a mock object
let mut mock = CoolTraitMock::new();

// Set up expectations for it
mock.expect_foo()
    .called_once();
mock.then()
    .expect_goop()
    .called_once()
    .with(true)
    .returning(|_| 5);

// Execute test code
m.foo();
assert_eq!(m.goop(true), 5);

// When the mock object is dropped, its expectations will be evaluated

请参阅 macros_high.rs 以查看模拟对象用户 API 的完整示例。

创建模拟对象

Simulacrum 提供了不同抽象级别的多个 API,因此您可以使用所需级别的控制创建模拟对象。使用 Simulacrum 创建的所有模拟对象都公开了相同的用户 API,无论使用哪个 API 级别创建它们。

以下示例均展示了如何模拟此特性

trait CoolTrait {
    fn foo(&self);
    fn goop(&mut self, flag: bool) -> u32;
    fn store(&self, val: &i64);
}

请注意,宏 API 仅支持从特性创建模拟,而手动 API 允许您创建代表结构体的模拟对象。

高级宏示例

create_mock! 宏从特性创建模拟对象。只需复制特性的接口并添加注释即可

extern crate simulacrum;

use simulacrum::*;

create_mock! {
    impl CoolTrait for CoolTraitMock (self) {
        expect_foo("foo"):
        fn foo(&self);

        expect_goop("goop"):
        fn goop(&mut self, flag: bool) -> u32;

        // & params are mocked as *const and &mut are mocked as *mut.
        expect_store("store"):
        fn store(&self, val: &i64);
    }
}

请参阅 macros_high.rs 以了解如何使用 create_mock! 模拟不同类型的示例。

中级宏示例

如果您需要比高级宏提供更多控制,可以使用 create_mock_struct!was_called! 宏。如果您需要创建高级宏不支持的功能的模拟对象,如泛型方法,这非常有用。请注意,您还可以将这些宏与手动接口混合使用。

extern crate simulacrum;

use simulacrum::*;

create_mock_struct! {
    struct CoolTraitMock: {
        expect_foo("foo");
        expect_goop("goop") bool => u32;
        // Note that we've used *const instead of & for shared references.
        expect_store("store") *const i64;
    }
}

impl CoolTrait for CoolTraitMock {
    fn foo(&self) {
        was_called!(self, "foo")
    }

    fn goop(&mut self, flag: bool) -> u32 {
        was_called!(self, "goop", (flag: bool) -> u32)
    }

    fn store(&self, val: &i64) {
        // Again note the use of *const instead of & for shared references.
        was_called!(self, "store", (val: *const i64))
    }
}

请参阅 macros_mid.rs 以获取如何使用中级宏模拟不同类型方法的高级示例。

手动示例

手动创建模拟对象以获得最大控制权。使用此API,您甚至可以创建模拟来代替结构体而不是特质。有关API的详细示例,请参阅 manual.rs

extern crate simulacrum;

use simulacrum::*;

trait CoolTrait {
    fn foo(&self);
    fn goop(&mut self, flag: bool) -> u32;
}

pub struct CoolTraitMock {
    e: Expectations
}

impl CoolTraitMock {
    pub fn new() -> Self {
        Self {
            e: Expectations::new()
        }
    }

    pub fn then(&mut self) -> &mut Self {
        self.e.then();
        self
    }

    pub fn expect_foo(&mut self) -> Method<(), ()> {
        self.e.expect::<(), ()>("foo")
    }

    pub fn expect_goop(&mut self) -> Method<bool, u32> {
        self.e.expect::<bool, u32>("goop")
    }
}

impl CoolTrait for CoolTraitMock {
    fn foo(&self) {
        self.e.was_called::<(), ()>("foo", ())
    }

    fn goop(&mut self, flag: bool) -> u32 {
        self.e.was_called_returning::<bool, u32>("goop", flag)
    }
}

依赖项

~19KB