我使用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/