【发布时间】:2021-01-29 13:41:59
【问题描述】:
我创建了一个 Server 结构,它由 2 个端口、一个 IP 地址和一个端口组成。
无法指定分配给端口的值,但它是从系统的环境变量中读取的。当没有找到环境变量,或者它不是一个有效值时,它默认为标准端口。
struct Server {
ip: String,
port: u16,
}
impl Server {
const STD_PORT: u16 = 4333;
const PORT_ENV_VAR: &'static str = "MEMDB_PORT";
fn new(ip: String) -> Server {
Server {
ip: ip,
port: Server::get_port(),
}
}
fn get_port() -> u16 {
match env::var(Server::PORT_ENV_VAR) {
Ok(val) => match val.parse::<u16>() {
Ok(val) => val,
Err(_) => Server::STD_PORT,
},
Err(_) => Server::STD_PORT,
}
}
}
当我想为它创建测试时,可以通过以下方式完成:
#[cfg(test)]
mod tests {
use crate::Server;
#[test]
fn test_create_server_assigns_correct_ip() {
// WHEN:
let server = crate::Server::new("127.0.0.1".to_owned());
// THEN:
assert_eq!(server.ip, "127.0.0.1");
}
#[test]
fn test_create_server_assigns_correct_port() {
// WHEN:
let server = crate::Server::new("".to_owned());
// THEN:
assert_eq!(server.port, 4333);
}
}
当然,当环境变量 MEMDB_PORT 被赋值时,这个测试会产生不同的结果。
如何验证分配的端口是否可以通过设置正确的环境变量来控制?
我正在考虑创建一个特征来定义 API 以访问系统的环境变量。
trait EnvironmentReader {
fn get(key: &str) -> Option<String>;
}
struct OSEnvironmentReader {}
impl EnvironmentReader for OSEnvironmentReader {
fn get(key: &str) -> Option<String> {
return match env::var(key) {
Ok(val) => Some(val),
Err(_) => None,
};
}
}
这是如何在 Rust 中做到这一点的正确方法吗? 如果是这样,我应该如何修改我的结构来使用这个特性?将其作为字段添加到结构本身,我该如何使用新的“dyn”内容?
【问题讨论】:
-
您可以在测试中使用 std::env::set_var 来设置测试期间的环境变量。
-
这不是最佳解决方案。如果我改用文件系统,您可能会争辩说我可以在测试中创建临时文件来进行测试,但这会大大降低测试速度。我真的需要一种方法来模拟这些依赖关系,只是寻找如何做到这一点的“Rust”方式。
-
在这种情况下,您可能需要一些通用的配置处理程序特征,您可以将其作为
Box<dyn Config>注入您的服务器并交换不同的实现以进行测试。 -
这就是我遇到的一些问题。我有一个特点(看我的代码,但不知道如何正确使用它,盒子的东西......)
标签: rust