Unit testing 为测试创建“std::env::Args”迭代器

Unit testing 为测试创建“std::env::Args”迭代器,unit-testing,rust,parameter-passing,Unit Testing,Rust,Parameter Passing,Rust中是否有方法从Vec创建std::env::Args,以便在#[test]函数中使用它 我希望测试一个函数,该函数获取一个std::env::Args作为参数,但我不知道如何使用我为测试提供的参数列表创建这样一个对象 我无法从文档、源文件或谷歌搜索中找到这个字段。的字段没有文档记录,而且似乎没有一个公共函数可以创建一个带有自定义字段的字段。所以,你在那里太不走运了 但由于它只是“一个进程参数的迭代器,为每个参数生成一个字符串值”,因此函数可以使用字符串迭代器或Vec,而不会损失任何功能或

Rust中是否有方法从
Vec
创建
std::env::Args
,以便在
#[test]
函数中使用它

我希望测试一个函数,该函数获取一个
std::env::Args
作为参数,但我不知道如何使用我为测试提供的参数列表创建这样一个对象

我无法从文档、源文件或谷歌搜索中找到这个字段。

的字段没有文档记录,而且似乎没有一个公共函数可以创建一个带有自定义字段的字段。所以,你在那里太不走运了

但由于它只是“一个进程参数的迭代器,为每个参数生成一个
字符串
值”,因此函数可以使用
字符串
迭代器或
Vec
,而不会损失任何功能或类型安全性。因为它只是一个
String
s的列表,所以任意将函数限制为恰好来自命令行的字符串没有多大意义

仔细看,他们就是这么做的。有很多
let args:Vec=env::args().collect()

甚至在某些地方,他们去掉了程序名,只提供了参数列表

use std::env;

use bootstrap::{Config, Build};

fn main() {
    let args = env::args().skip(1).collect::<Vec<_>>();
    let config = Config::parse(&args);
    Build::new(config).build();
}
我不是铁锈专家,但铁锈专家似乎就是这样处理这个问题的。

很好,这让我想到了这个更简单的版本。由于
std::env::Args
使用
Item=String
实现了
Iterator
,因此可以执行以下操作:

使用std::env;
fn解析(args:T)
哪里
T:迭代器,
{
用于arg中的arg{
//arg:字符串
打印!(“{}”,arg);
}
}
fn main(){
解析(env::args());
}
为了进行测试,您在
字符串上提供了一个迭代器
parse

#[测试]
fn test_parse(){
设args=[“arg1”,“arg2”].iter().map(|s|s.to_string());
解析(args);
}

我编写了一个小宏,使这一过程更加简单,基于(因此也基于;感谢两者):

macro\u规则!制作字符串{
($($element:expr),*)=>{
{
让mut v=Vec::new();
$(v.push(字符串::from($element));)*
v、 进入()
}
};
}
它可以这样使用:

macro\u规则!制作字符串{
($($element:expr),*)=>{
{
让mut v=Vec::new();
$(v.push(字符串::from($element));)*
v、 进入()
}
};
}
//我们使用这个函数来测试我们的宏
fn打印参数(参数:T){
对于args中的项目{
println!(“{}”,项目);
}
}
fn main(){
//打印a、b和c
打印参数(生成字符串)(“a”、“b”、“c”))
}
或者在网上试一试


我(还)不是锈病专家,任何建议都是非常受欢迎的:)

你能改变函数,让它使用一个通用的
I:Iterator
?这更容易建模。@trentcl,很好的解决方法,但这是惯用的生锈吗?我必须放弃这个函数希望得到命令行参数的明确意图吗?这个函数希望一些通用迭代器为它生成可测试的字符串?在您接受的情况下,通用是一种方法。函数名可以表示意图,但使用泛型输入类型可以保持函数的灵活性。是吗?如果函数的约定是“接受命令行参数”,那么测试它的唯一正确方法就是传递命令行参数。您必须放松契约,以便能够使用任意字符串对其进行测试。(但是我应该在Iterator
中提到
而不是
Iterator
,因为这将对
Vec
起作用)除此之外,我倾向于同意loganfsmyth,但是如果出于某种原因,对调用方强制执行“给我命令行参数”很重要,您可以将泛型函数及其测试包装在一个模块中,并且只公开一个准确地接受
Args
pub fn
(并调用泛型版本来完成这项工作)。虽然在这一点上,您也可以自己调用
std::env::args()
而不使用任何参数.FWIW,但在现有的答案中已经提到了这一点:“您的函数可以使用
字符串
迭代器”。使用
迭代器
可能会在某一点上简化代码(
fn parse)(args:impl-IntoIterator)
)。要非常灵活,请接受任何可以被视为
&str
fn parse(args:impl-IntoIterator)
)或
的内容。
impl Config {
    pub fn parse(args: &[String]) -> Config {
        let flags = Flags::parse(&args);
        ...