1 个不稳定版本

0.1.0 2022年7月4日

#497 in 测试

MIT/Apache

50KB
581

Rust 轻量级模仿/间谍库

Build Status License: MIT OR Apache-2.0 rust 1.57+ required

文档: crate docs (main)

Rust 中的模仿与面向对象语言相比要困难一些。因为没有隐式/全面的类层次结构,所以不适用Liskov 替换原则,因此通常不可能用模拟对象替换实际对象。只有在对象消费者通过参数多态或动态分派明确选择的情况下才能切换。

做什么?此库没有尝试模仿面向对象世界的模仿方法,而是选择了一种类似 serde 的远程 derive 的另一种方法。模仿是在函数/方法级别上进行的,每个函数都会条件性地代理到一个可以访问函数参数的模拟,并可以做任何事情:调用“真实”函数(例如,为了监视响应),可能带有不同的参数,并在修改参数后执行;用模拟响应替换,等等。自然,模拟逻辑可以是状态的(例如,从预定义的列表中确定响应;记录监视函数的响应等。)

用法

将以下内容添加到您的 Crate.toml

[dev-dependencies]
mimicry = "0.1.0"

用法示例

use mimicry::{mock, CallReal, Mock, Mut};

// Tested function
#[mock(using = "SearchMock")]
fn search(haystack: &str, needle: char) -> Option<usize> {
    haystack.chars().position(|ch| ch == needle)
}

// Mock logic
#[derive(Default, Mock)]
#[mock(mut)]
// ^ Indicates that the mock state is wrapped in a wrapper with 
// internal mutability.
struct SearchMock {
    called_times: usize,
}

impl SearchMock {
    // Implementation of mocked function, which the mocked function
    // will delegate to if the mock is set.
    fn search(
        this: &Mut<Self>,
        haystack: &str,
        needle: char,
    ) -> Option<usize> {
        this.borrow().called_times += 1;
        if haystack == "test" {
            Some(42)
        } else {
            let new_needle = if needle == '?' { 'e' } else { needle };
            this.call_real(|| search(haystack, new_needle))
        }
    }
}

// Test code.
let guard = SearchMock::default().set_as_mock();
assert_eq!(search("test", '?'), Some(42));
assert_eq!(search("needle?", '?'), Some(1));
assert_eq!(search("needle?", 'd'), Some(3));
let recovered = guard.into_inner();
assert_eq!(recovered.called_times, 3);

有关更多详细信息和用法示例,请参阅库文档。

功能

  • 可以模仿具有各种签名(包括泛型函数、非静态类型参数的函数、返回非静态响应的函数和具有依赖生命周期的响应等)的函数/方法。
  • 可以在 impl 块中模仿方法,包括特质实现。
  • 单个模仿函数可以模仿多个函数,前提是它们的签名兼容。
  • 是否在函数/方法之间共享模拟状态完全取决于测试编写者。同一接收类型/在同一 impl 块中的函数可能具有不同的模拟状态。
  • 模拟函数可以具有比被模拟函数签名所需的更宽泛的参数类型。例如,如果模拟函数没有使用某些参数,可以将它们替换为无约束的类型参数。

缺点

  • 仍然不能模拟来自其他crate的类型。
  • 即使模拟逻辑没有使用某些参数,也需要正确构造它们,这可能在某些情况下违背了使用模拟的原因。
  • 内置的匹配/验证功能非常有限。使用所选方法,通常更简单、更透明地使用 match 语句。作为缺点,如果匹配逻辑需要在多个测试中进行定制,这主要取决于测试编写者。

替代方案

mockallsimulacrummocktopusmockiato 等,提供了基于为被调用的函数/方法配置预期的更传统的模拟方法。

许可证

根据您的选择,在Apache License, Version 2.0MIT license 下许可。

除非您明确声明,否则您提交给 mimicry 的任何有意贡献,根据 Apache-2.0 许可证的定义,应按上述方式双重许可,不附加任何其他条款或条件。

依赖关系

~1.6–7MB
~47K SLoC