Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.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
C# zip方法中的意外行为_C#_Linq_Unit Testing - Fatal编程技术网

C# zip方法中的意外行为

C# zip方法中的意外行为,c#,linq,unit-testing,C#,Linq,Unit Testing,我有以下代码: [TestMethod()] public void Test_Changed() { var All = repository.GetProducts().Select(c => c.Price).ToList(); var Original = All.ToList(); //The following line updates all prices but should has no effect //Because I've used

我有以下代码:

[TestMethod()]
public void Test_Changed()
{
    var All = repository.GetProducts().Select(c => c.Price).ToList();
    var Original = All.ToList();
    //The following line updates all prices but should has no effect
    //Because I've used ToList already in All query
    reducer.ReducePrice(amount);
    All.Zip(Original, (f, s) =>
    {
        if (f == s)
        {
            Assert.Fail();
        }
        return f;
    });
}
我原以为我的测试会失败,但它成功地通过了。我真想知道这怎么可能?如下所示,
所有
原始
变量具有相同的值,那么为什么
Assert.Fail()从未执行

如果我从
All
查询中删除
ToList
,由于延迟执行,测试应按预期通过,但当我使用
ToList
时,后面的更改应无效。那为什么我的考试通过了呢

另请参阅:

var res = All.Zip(Original, (f, s) =>
{
    if (f == s)
    {
        Assert.Fail();
    }
    return f;
});
结果是:

但测试结果:


与许多LINQ操作一样,
Zip
是惰性的-您的lambda表达式从未被执行,因为您正在调用
Zip
,但从未使用结果

如果您将测试更改为执行以下操作:

var list = All.Zip(...).ToList();
那么我怀疑你会看到断言失败。(或者调用
Count()
,或者在整个序列中进行迭代的任何其他操作。)

或者正如Jamiec所说,添加一个断言。它可以简单到:

Assert.IsFalse(All.Zip(Original, (f, s) => f == s).Any(x => x));

(这实际上取决于您要检查的内容-不同的断言将为您提供不同类型的信息。)

如果您找到了匹配的对,并且如果找到了任何对,则测试将失败,您的测试会更好

var result = All.Zip(Original, (f, s) =>
    {            
        return f == s;
    });
Assert.IsFalse(result.Where(x => x).Any());
// or: Assert.IsFalse(result.Any(x => x)); 

另一方面,现在是开始遵循.NET命名约定的好时机。在声明结果时,您是否可以规范化您的术语:如果测试应该断言.Fail,但它没有失败,那么它没有“成功通过”——它“运行到完成”。使用“Asserts”作为动词表示“called Assert.Fail()”也是可以的,当这是“Success”条件时。我已经试过了。我看到断言失败了,但我的测试仍然通过!对我来说,这听起来不太可能-请提供一个解决方案,以便我们可以尝试重现问题。如果执行的是
Assert.Fail
,则应引发适当的异常。请注意,如果在调试器中扩展结果时只说调试器中的断言失败,这与在实际测试中强制执行不同。@SteveCode解决方案的诊断非常正确,但我要提到的是,与其让LINQ查询执行副作用,为了确保这些副作用确实发生,最好使用一个没有副作用的查询,搜索您关心的值,然后在处理查询结果时产生副作用。在这种情况下,这意味着编写一个搜索匹配对的查询,然后如果在查询结果中找到匹配对,则将失败。@SteveCode您完全按照Jon在上面的评论中所说的做了。您已经在枚举它的调试器中展开了它。您需要在实际测试中使用
ToList
/
ToArray
@SteveCode强制执行代码,这将使代码正常工作,但它不是好的设计,而且非常脆弱,原因我在前面的评论中提到过。更好的解决方案是重新构造查询,只返回一个可以断言的值,而不是在查询本身中断言<代码>结果
是一系列布尔值。您需要检查是否有任何值为真,而不是序列中是否有布尔值。请注意,
Any
接受谓词,因此不需要
Where
@Servy,我想您在更新之前已经看到了。当然,对于谓词,没有区别,也可以看到我评论的后半部分。@Servy同上:D