如何在C#/VS中构建自定义断言?

3

我遇到了一个从一些文本中提取元数据并将其放入字典的代码中的错误。

当我比较两个字典对象时,我的测试失败了,因为键的顺序不同。我并不真正关心键的顺序。

我希望有一个类似于assert方法的可用方法:

Assert.AreEquivalent(propsExpected,propsActual)

那将会被评估为:
Assert.AreEqual(propsExpected.Count, propsActual.Count);
foreach (var key in propsExpected.Keys)
{
    Assert.IsNotNull(props[key]);
    Assert.AreEqual(propsExpected[key], props[key]);
}

如何最好地做到这一点?

7个回答


1

正如@Sprintstar在@Michael La Voie的答案评论中指出的那样,由于其静态性质,无法扩展Assert类。我通常解决这个问题的方法是创建一个测试存储库,其中包含我的自定义方法,多个断言和其他验证在同一方法中进行。例如-

public static class MyTestRepository
{   
    public static void ArePropsEquivalent(
        Dictionary<string, int> propsExpected, 
        Dictionary<string, int> propsActual)
    {
        //Multiple Asserts and validation logic
        //required for Equivalence goes here
    }

    public static void ArePropsSimilar(
        Dictionary<string, int> propsExpected, 
        Dictionary<string, int> propsActual)
    {
        //Multiple Asserts and validation logic 
        //required for similarity goes here
    }
}

我会将这些方法从单元测试方法中调用。
[TestMethod]
public void TestMthod1()
{
    //Props declaration goes here
    MyTestRepository.ArePropsEquivalent(propsExpected, propsActual);
}

[TestMethod]
public void TestMthod2()
{
    //Props declaration goes here
    MyTestRepository.ArePropsSimilar(propsExpected, propsActual);
}

这样我就可以在实际的单元测试用例方法中编写更少的代码并做更多的事情,保持模块化(以适应不同的模型)。

1

如果您能够使用LINQ,


void Main()
{
    Dictionary d1 = new Dictionary<int, string>();
    Dictionary d2 = new Dictionary<int, string>();
d1.Add(1, "1"); d1.Add(2, "2"); d1.Add(3, "3");
d2.Add(2, "2"); d2.Add(1, "1"); d2.Add(3, "3");
Console.WriteLine(d1.Keys.Except(d2.Keys).ToArray().Length); }

这将在控制台打印0。在上面的示例中,Except尝试查找两个列表之间的差异。

您可以将此与0进行比较,以查找是否存在任何差异。

编辑:在执行此操作之前,您可以添加比较2个字典长度的检查。
即,只有在长度不同时才能使用Except。


1
使用NUnit,您可以使用Is.EquivalentTo()约束来比较两个集合。该约束将评估集合并检查集合是否具有相同的元素,但它不关心顺序。
如果您不使用NUnit,则可能在您正在使用的测试框架中存在类似的东西?CollectionEquivalentConstraint文档

1

现在已经可以实现(可能是由于MS在最初回答该问题后添加了此功能)- 如果使用That单例,扩展将起作用。

在这种情况下,扩展可以被称为:

Assert.That.AreEquivalent(propsExpected,propsActual);


-2

这里的技巧是使用 .Net 3.5 的一个新特性,称为扩展方法

例如,要使用上面提供的代码使 Assert 类支持 AreEquivalent 方法,您可以像这样操作:

public static class MyAssertExtensions
{
    public static void AreEquivalent(this Assert ast, 
        Dictionary<string, int> propsExpected, 
        Dictionary<string, int> propsActual)
    {
        Assert.AreEqual(propsExpected.Count, propsActual.Count);
        foreach (var key in propsExpected.Keys)
        {
            Assert.IsNotNull(props[key]);
            Assert.AreEqual(propsExpected[key], props[key]);
        }
    }
}

这样你就可以像这样调用断言:

Assert.AreEquivalent(propsExpected,propsActual);

问题在于,如果两个字典中的元素顺序不同,即使这些元素相等,断言也会失败。 - user434917
@Marwan:不,它仅断言集合具有相同的大小,并且对于集合1中的每个键,集合2中也存在相同的键并具有相同的值。顺序从未成为问题。 - GalacticCowboy
要调用此函数,您需要使用 'Assert.That.AreEquivalent()'。 - miguelmpn
2
你不能为Assert创建扩展方法,因为它是一个静态类,请参见:https://dev59.com/lFrUa4cB1Zd3GeqPhCVF - John Barton

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