我使用mocker测试了我的项目。我不知道say_hello_brother需要哪种类型的转换。下面是简化的代码列表:

lib.rs

#![feature(plugin, custom_derive)]
#![plugin(mockers_macros)]
#[cfg(test)]
extern crate mockers;

use mockers::Scenario;

#[derive(Mock)]
trait SayHello {
    fn hello(&self);
}

// assume `SayHello` is a service and  worked on multiple threads
fn say_hello_brother<T: SayHello + Sync>(brother: &'static T) {
    brother.hello()
}

#[test]
fn test_sya_hello() {
    let scenario = Scenario::new();
    let mock = scenario.create_mock_for::<SayHello>();
    say_hello_brother(&mock)
}

Cargo.toml
[package]
name = "mock"
version = "0.1.0"
authors = ["llxxb"]

[dependencies]
mockers = "0.9.4"
mockers_macros = "0.9.4"

和错误信息:

error[E0277]: the trait bound `std::rc::Rc<std::cell::RefCell<mockers::ScenarioInternals>>: std::marker::Sync` is not satisfied in `SayHelloMock`
  --> src\lib.rs:22:5
   |
22 |     say_hello_brother(&mock)
   |     ^^^^^^^^^^^^^^^^^ `std::rc::Rc<std::cell::RefCell<mockers::ScenarioInternals>>` cannot be shared between threads safely
   |
   = help: within `SayHelloMock`, the trait `std::marker::Sync` is not implemented for `std::rc::Rc<std::cell::RefCell<mockers::ScenarioInternals>>`
   = note: required because it appears within the type `SayHelloMock`

更新经过一番尝试,我成功地将Sync附加到SayHelloMock。新的lib.rs:
#![feature(plugin, custom_derive)]
#![plugin(mockers_macros)]
#[cfg(test)]
extern crate mockers;

use mockers::Scenario;

trait SayHello {
    fn hello(&self);
}


mock! {
    SayHelloMock,
    self,
    trait SayHello {
        fn hello(&self);
    }
}

unsafe impl Sync for SayHelloMock {}


// assume `SayHello` is a service and  worked on multiple threads
fn say_hello_brother<T: SayHello + Sync>(brother: &'static T) {
    brother.hello()
}

#[test]
fn test_sya_hello() {
    let scenario = Scenario::new();
// not work
//    let mock = scenario.create_mock::<SayHelloMock>();
//    static MOCK: SayHelloMock = || { mock };
//    say_hello_brother(&MOCK)

    // not work yet
    let mock : &'static SayHelloMock = &(scenario.create_mock::<SayHelloMock>());
    say_hello_brother(mock)
}

但我仍然无法将其转换为“静态错误信息:
error[E0597]: borrowed value does not live long enough
--> src\lib.rs:38:41
|
38 |     let mock : &'static SayHelloMock = &(scenario.create_mock::<SayHelloMock>());
|                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
39 |     say_hello_brother(mock)
40 | }
| - temporary value only lives until here
|
= note: borrowed value must be valid for the static lifetime...

最佳答案

您不能为此目的使用模拟程序库,因为它生成的模拟程序是not thread safe

话虽这么说,但没有什么可以限制您创建自己的线程安全的模拟程序:

use std::sync::atomic::{AtomicUsize, Ordering};

#[derive(Debug, Default)]
struct MyMock {
    call_count: AtomicUsize,
}

impl SayHello for MyMock {
    fn hello(&self) {
        self.call_count.fetch_add(1, Ordering::SeqCst);
    }
}

但是,您的签名需要&'static T,这实际上可能是一个糟糕的主意。您将需要使用类似惰性的东西:
#[macro_use]
extern crate lazy_static;

#[test]
fn test_say_hello() {
    lazy_static! {
        static ref MOCK: MyMock = MyMock::default();
    };
    say_hello_brother(&*MOCK);
    assert_eq!(MOCK.call_count.load(Ordering::SeqCst), 1);
}

关于unit-testing - 如何为需要“静态生命期”引用并实现Sync的函数赋予模拟值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49093092/

10-11 22:08
查看更多