7 个版本

0.2.4 2024年6月22日
0.2.3 2024年1月5日
0.1.1 2024年1月4日

#138测试

Download history 18/week @ 2024-05-02 83/week @ 2024-05-09 24/week @ 2024-05-16 18/week @ 2024-05-23 61/week @ 2024-05-30 9/week @ 2024-06-06 119/week @ 2024-06-13 343/week @ 2024-06-20 149/week @ 2024-06-27 157/week @ 2024-07-04 182/week @ 2024-07-11 183/week @ 2024-07-18 183/week @ 2024-07-25 114/week @ 2024-08-01 64/week @ 2024-08-08 49/week @ 2024-08-15

每月469次下载

MIT/Apache

24KB
328 代码行

Mock'em

github crates.io docs.rs

Mock Rust 中的任何函数。

请确保仅将此crate用于测试目的,因为它将给您的代码添加很多开销。

基本用法

在您想mock的函数上,添加 #[mock] 属性。

#[cfg_attr(test, mockem::mock)]
fn foo(a: &str) -> String {
    format!("{a}")
}

fn bar() -> String {
    format!("Hello, {}!", foo("bar"))
}

#[test]
fn test_fn() {
    use mockem::MockCall;

    foo.mock_once(|a| format!("mocked {a}"));

    assert_eq!(&bar(), "Hello, mocked bar!");

    // function works normally after mock return value is returned
    assert_eq!(&bar(), "Hello, bar!");
}

重复mock

如果您想对一个函数进行多次或无限次mock,请使用 mock_repeat 而不是 mock_once

mock_repeat 的第一个参数是一个 Option<usize>,表示mock函数的次数;

None 表示无限次mock。

#[cfg_attr(test, mockem::mock)]
fn foo(a: &str) -> String {
    format!("{a}")
}

fn bar(a: &str) -> String {
    format!("Hello, {}!", foo(a))
}

#[test]
fn test_fn() {
    use mockem::{MockCall, ClearMocks};

    foo.mock_repeat(None, |a| format!("mocked {a}"));

    assert_eq!(&bar("bar"), "Hello, mocked bar!");
    assert_eq!(&bar("foo"), "Hello, mocked foo!");
    assert_eq!(&bar("baz"), "Hello, mocked baz!");

    // this clears all mocks, which will stop the indefinite mock
    foo.clear_mocks();

    assert_eq!(&bar("baz"), "Hello, baz!");
}

实现块

如果您想mock impl方法,请将 #[mock] 属性添加到impl块中。同样,对于impl trait方法也这样做。

这将mock impl块中的所有方法。

struct Foo;

#[cfg_attr(test, mockem::mock)]
impl Foo {
    fn foo(&self) -> String {
        format!("foo")
    }
}

trait Baz {
    fn baz(&self) -> String;
}

#[cfg_attr(test, mockem::mock)]
impl Baz for Foo {
    fn baz(&self) -> String {
        format!("baz")
    }
}

fn bar() -> String {
    format!("Hello, {} and {}!", Foo.foo(), Foo.baz())
}

#[test]
fn test_fn() {
    use mockem::MockCall;

    Foo::foo.mock_once(|_| "mockem".to_owned());
    Foo::baz.mock_once(|_| "mockem2".to_owned());

    assert_eq!(&bar(), "Hello, mockem and mockem2!");
}

异步函数

异步函数也受支持。

use async_trait::async_trait;

struct Foo;

#[cfg_attr(test, mockem::mock)]
impl Foo {
    async fn foo(&self) -> String {
        format!("foo")
    }
}

#[async_trait]
trait Baz {
    async fn baz(&self) -> String;
}

// also works with async_trait
// but you must place #[mock] above #[async_trait]
#[cfg_attr(test, mockem::mock)]
#[async_trait]
impl Baz for Foo {
    async fn baz(&self) -> String {
        format!("baz")
    }
}

async fn bar() -> String {
    format!("Hello, {} and {}!", Foo.foo().await, Foo.baz().await)
}

#[test]
fn test_fn() {
    use mockem::MockCall;
    
    Foo::foo.mock_once(|_| "mockem".to_owned());
    Foo::baz.mock_once(|_| "mockem2".to_owned());
    
    assert_eq!(&bar().await, "Hello, mockem and mockem2!");
}

依赖

~250–700KB
~17K SLoC