断言两种不同类型的枚举是等价的

Mat*_*hew 6 .net c# nunit unit-testing

我有一个NUnit单元测试,我有两个不同类型的集合,我想断言是等价的.

class A { public int x; }
class B { public string y; }

[Test]
public void MyUnitTest()
{
    var a = GetABunchOfAs(); // returns IEnumerable<A>
    var b = GetABunchOfBs(); // returns IEnumerable<B>

    Assert.IsPrettySimilar(a, b, (argA, argB) => argA.ToString() == argB);
}
Run Code Online (Sandbox Code Playgroud)

在哪里Assert.IsPrettySimilar定义如此

public static void IsPrettySimilar<T1, T2>(
    IEnumerable<T1> left, 
    IEnumerable<T2> right, 
    Func<T1, T2, bool> predicate)
{
    using (var leftEnumerator = left.GetEnumerator())
    using (var rightEnumerator = right.GetEnumerator())
    {       
        while (true)
        {
            var leftMoved = leftEnumerator.MoveNext();

            if (leftMoved != rightEnumerator.MoveNext()) 
            {
                Assert.Fail("Enumerators not of equal size");
            }

            if (!leftMoved)
            {
                break;
            }

            var isMatch = predicate(leftEnumerator.Current, 
                                rightEnumerator.Current);

            Assert.IsTrue(isMatch);
        }           
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,是否有更惯用的方式使用NUnit中的现有方法执行上述操作?我已经看过了,CollectionAssert并没有什么能与我想要做的相提并论.

在这种情况下,我对"等效"的描述是:

1)集合必须具有相同的大小
2)集合必须具有相同的逻辑顺序
3)必须使用某些谓词来确定匹配项之间的等价性.

Ser*_*kiy 1

让我们想想你要测试什么。您并不是试图测试第一个序列中的对象与第二个序列中的对象是否相同。它们可能非常不同。所以,“相似”这个词在这里是非常模糊的。您在这里真正想要测试的是,第一个序列的某些投影等于第二个序列的其他投影。而 NUnit 已经具备这样的功能:

 CollectionAssert.AreEqual(bunchOfAs.Select(a => a.ToString()),
                           bunchOfBs.Select(b => b));
Run Code Online (Sandbox Code Playgroud)

因此,您可以投影两个序列来获取特定数据,然后您可以为这两个投影指定好听的名称,这将使您的测试对其他人来说是可读的。这里有一些隐藏的业务逻辑,在代码中没有解释 - 你没有解释为什么做出这样的预测。因此,投影结果的好名称将解释您的意图。例如:

 var expectedNames = employees.Select(u => u.Login);
 var actualNames = customers.Select(c => c.Name);
 CollectionAssert.AreEqual(expectedNames, actualNames);
Run Code Online (Sandbox Code Playgroud)

这对我来说比

 Assert.IsPrettySimilar(employees, customers, (e, c) => u.Login == c.Name);
Run Code Online (Sandbox Code Playgroud)