Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 从函数返回惰性静态互斥体的MutexGuard需要一个生存期参数_Rust - Fatal编程技术网

Rust 从函数返回惰性静态互斥体的MutexGuard需要一个生存期参数

Rust 从函数返回惰性静态互斥体的MutexGuard需要一个生存期参数,rust,Rust,我正在使用模拟函数编写测试,用互斥体控制测试中的返回值: #[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 multip

我正在使用模拟函数编写测试,用
互斥体控制测试中的返回值:

#[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()));
    }
}

请帮我更正。

阅读完整的错误消息:

考虑给它一个显式的有界生存期或“静态生存期”

这样做可以:

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 set\u hello\u return\u值(rtn:String)->MutexGuard字符串
哪里
G:问候,
{
问候者。说你好(name.into())
}
特质问候语{
fn说你好(&self,name:&str)->String;
}
结构RealGreeting;
impl问候语用于RealGreeting{
fn说你好(&self,name:&str)->String{
格式!(“你好,{}”,名称)
}
}
#[cfg(测试)]
模试验{
使用超级::*;
使用std::cell::RefCell;
结构模拟问候语{
fn新(值:&'a str)->自我{
自我{
价值
使用:Default::Default()调用了_,
}
}
}
恳求{
fn说你好(&self,name:&str)->String{
self.called_with.borrow_mut().push(name.to_owned());
self.value.to_owned()
}
}
#[测试]
fn test1(){
让g=MockGreeting::new(“Hello”);
让r=你使用的东西说你好(&g,“汤姆”);
断言_eq!(“你好,r”);
assert_eq!(&*g.called_with.borrow(),&[“Tom.to_string());
}
}

为什么要返回
MutexGuard
类型?若要锁定并避免其他测试以设置可能导致断言错误的值,请不要编辑问题以包含答案。如果你有一些实质性的补充,我们鼓励你把自己的答案贴在下面。但是,您的代码与您接受的答案完全相同。既然你接受了它,这对以后读到这篇文章的人来说已经足够了。我已经从你的问题中删除了这个。太好了,我学了一辈子新语法。谢谢顺便说一下,测试运行良好,但如果我不锁定它们,它们将失败。如果它像你说的那样,如何达到我的目的。我的上帝!你能给我一段示例代码来学习吗。我来自java,我的想法有很多OOconcepts@llxxbbJava完全充满了依赖注入;这不是Rust独有的概念,甚至不是非常新的概念。我加了一张草图,画出了它的样子。通过参数传递所有需要的信息,并模拟必须是
Trait
的参数。我误解了依赖项注入,所有注入都必须手动完成,而不是由某些板条箱或其他东西自动完成。再次感谢。
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()));
    });
}
fn thing_that_uses_say_hello<G>(greeter: &G, name: &str) -> String
where
    G: Greeting,
{
    greeter.say_hello(name.into())
}

trait Greeting {
    fn say_hello(&self, name: &str) -> String;
}

struct RealGreeting;

impl Greeting for RealGreeting {
    fn say_hello(&self, name: &str) -> String {
        format!("Hello, {}", name)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::cell::RefCell;

    struct MockGreeting<'a> {
        called_with: RefCell<Vec<String>>,
        value: &'a str,
    }

    impl<'a> MockGreeting<'a> {
        fn new(value: &'a str) -> Self {
            Self {
                value,
                called_with: Default::default(),
            }
        }
    }

    impl<'a> Greeting for MockGreeting<'a> {
        fn say_hello(&self, name: &str) -> String {
            self.called_with.borrow_mut().push(name.to_owned());
            self.value.to_owned()
        }
    }

    #[test]
    fn test1() {
        let g = MockGreeting::new("Hello");
        let r = thing_that_uses_say_hello(&g, "Tom");
        assert_eq!("Hello", r);
        assert_eq!(&*g.called_with.borrow(), &["Tom".to_string()]);
    }
}