我正在使用模拟函数编写测试,使用Mutex
控制测试中的返回值:
#[macro_use]
extern crate lazy_static;
#[cfg(test)]
pub use mock::*;
#[cfg(not(test))]
pub use real::*;
mod real {
pub fn say_hello(_name: String) -> String {
unimplemented!()
}
}
/// simulate multiple uses, replace `real` in test.
mod mock {
use std::sync::*;
lazy_static! {
pub static ref LOCK: Mutex<bool> = Mutex::new(true);
pub static ref HELLO_VALUE: Mutex<String> = Mutex::new(String::default());
}
pub fn say_hello(_name: String) -> String {
use std::ops::Deref;
HELLO_VALUE.lock().unwrap().deref().clone()
}
pub fn set_hello_return_value(rtn: String) -> MutexGuard<bool> {
let lock = LOCK.lock().unwrap();
let mut value = HELLO_VALUE.lock().unwrap();
*value = rtn;
lock
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test1() {
// repeated block begin--------------------------
let _lock = LOCK.lock().unwrap();
let mut value = HELLO_VALUE.lock().unwrap();
*value = "Hello Tom!".to_string(); // just this line is different from test2
drop(value);
// repeat block end--------------------------
assert_eq!("Hello Tom!", say_hello("".to_string()));
}
#[test]
fn test2() {
// repeated block begin--------------------------
let _lock = LOCK.lock().unwrap();
let mut value = HELLO_VALUE.lock().unwrap();
*value = "Hello Jack!".to_string(); // just this line is different from test1
drop(value);
// repeat block end--------------------------
assert_eq!("Hello Jack!", say_hello("".to_string()));
}
#[test]
fn test_simplified_but_not_work() {
let _lock = set_hello_return_value("Hello Mark!".to_string());
assert_eq!("Hello Mark!", say_hello("".to_string()));
}
}
您可以看到我想要简化的重复块。我创建了一个函数set_hello_return_value
,但编译器抱怨:
error[E0106]: missing lifetime specifier
--> src/main.rs:28:51
|
28 | pub fn set_hello_return_value(rtn: String) -> MutexGuard<bool> {
| ^^^^^^^^^^^^^^^^ expected lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
= help: consider giving it an explicit bounded or 'static lifetime
请帮我纠正。
答案 0 :(得分:1)
阅读完整的错误消息:
考虑给它一个明确的有界或'静态生命期
这样做有效:
public class A{
int num;
public A(){
}
public A(int num){this.num = num;}
}
public class B {
A a;
}
public class Main {
public static void main(String[] args) {
B b = new B();
System.out.println(b.a.num);//Will Throw Null pointer exception if you
try to access a,in any case it will not be 0
}
}
但是,我可能根本不会退回警卫:
pub fn set_hello_return_value(rtn: String) -> MutexGuard<'static, bool> {
let lock = LOCK.lock().unwrap();
let mut value = HELLO_VALUE.lock().unwrap();
*value = rtn;
lock
}
老实说,我不会做任何,因为条件编译太过分了。如果您需要单独测试系统的组件,他们不应该开始相互了解;他们应该依赖注入。这样做的另一个好处是每个测试都可以注入自己的值,从而保留了测试的多线程特性。
pub fn with_hello_return_value<S, F>(rtn: S, f: F)
where
S: Into<String>,
F: FnOnce(),
{
let _lock = LOCK.lock().unwrap();
*HELLO_VALUE.lock().unwrap() = rtn.into();
f()
}
#[test]
fn test_simplified() {
with_hello_return_value("Hello Mark!", || {
assert_eq!("Hello Mark!", say_hello("".to_string()));
});
}