有没有办法为 Rust 结构体附加一些调试字段?

3
例如,我想在测试时使结构体S只有一个name_count字段,这样我可以操作last_name来验证测试中与name_count相关的属性。
pub struct S {
    last_name: String,
    #[cfg(test)] {
        // This field only exists in tests
        name_count: HashMap<String, i32>,
    }
}

impl S {
    fn record_last_name(&mut self, name: String) {
        self.last_name = name;
        if cfg!(test) {
            // Increase self.name_count[self.last_name]
        }
    }
}

#[test]
fn test_last_name_count() {
    let mut s = S {};
    ...
    // assert some properties about name_count
}

然而,这段代码无法编译。看起来Rust不支持在结构体定义内部使用#[cfg(test)],那么我该如何解决这个问题呢?
1个回答

2
你可以这样做,但#[cfg(test)]是一个属性宏,因此它适用于其后的任何内容,不需要像你写的那样使用块范围。
你还需要在函数和方法中添加#[cfg(...)]属性,以确保你不会遇到“缺少字段”/“没有名为...的字段”的编译器错误。
use std::collections::HashMap;

pub struct S {
    last_name: String,
    #[cfg(test)]
    // This field only exists in tests
    name_count: HashMap<String, i32>,
}

impl S {
    #[cfg(test)]
    fn record_last_name(&mut self, name: String) {
        self.last_name = name;
        // Increase self.name_count[self.last_name]
    }
}

#[cfg(not(test))]
fn main() {
    let mut s = S { last_name: "Foo".to_string() };
}

#[test]
fn test_last_name_count() {
    let mut s = S { last_name: "Foo".to_string(), name_count: HashMap::new() };
    // assert some properties about name_count
}

3
这个定义不能使用 if cfg!(),必须使用 #[cfg()] - Chayim Friedman
你可以将 #[cfg()] 放在语句上,而不必对整个函数进行门控。 - Chayim Friedman
你是指 main 还是 record_last_name?我认为 main 可能需要在函数上使用它,除非他们想要为两个配置都管理一个 s。我将其保留在实现块的函数范围内,只是为了避免对他们需要该方法执行的操作进行假设,但是,是的,这个可以放在表达式上。 - Jeremy Meadows

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接