使用List<>的MSTest单元测试返回不工作

时间:2011-03-10 22:26:52

标签: unit-testing generics mstest

我有一个非常简单的单元测试,它正在测试通用List<SelectListItem>的正确生成。

    [TestMethod()]
public void PopulateSelectListWithSeperateTextAndValueLists()
{
    //Arrange
    SetupDisplayAndValueLists();
    bool allOption = false;

    //Act
    List<SelectListItem> result = ControllerHelpers.PopulateSelectList(valueList, displayList, allOption);

    //Assert
    Assert.AreEqual(expected, result);
}

Assert总是返回false,即使我已经检查并确认两个对象具有相同的确切值。

当单元测试返回泛型的结果时是否有任何特殊注意事项?

更新了新测试及其状态

Assert.AreEqual(4, result.Count); //passes

Assert.AreEqual(result[0].Text, expected[0].Text, "0 element is not found");//passes
Assert.AreEqual(result[1].Text, expected[1].Text, "1 element is not found");//passes
Assert.AreEqual(result[2].Text, expected[2].Text, "2 element is not found");//passes
Assert.AreEqual(result[3].Text, expected[3].Text, "3 element is not found");//passes

Assert.AreEqual(result[0].Value, expected[0].Value, "0 element is not found");//passes
Assert.AreEqual(result[1].Value, expected[1].Value, "1 element is not found");//passes
Assert.AreEqual(result[2].Value, expected[2].Value, "2 element is not found");//passes
Assert.AreEqual(result[3].Value, expected[3].Value, "3 element is not found");//passes

Assert.IsTrue(result.Contains(expected[0]), "0 element is not found"); //doesn't pass
Assert.IsTrue(result.Contains(expected[1]), "1 element is not found"); //doesn't pass
Assert.IsTrue(result.Contains(expected[2]), "2 element is not found"); //doesn't pass
Assert.IsTrue(result.Contains(expected[3]), "3 element is not found"); //doesn't pass

Assert.AreEqual(expectedList, result); //doesn't pass

3 个答案:

答案 0 :(得分:3)

使用CollectionAssert类而不是Assert类。您可以选择验证项目的顺序是否相同,或者只是它们的整体项目相同。

同样,如果您的集合中的项目是引用类型而不是值类型,则可能无法按照您的需要进行比较。 (虽然字符串可以正常工作)

更新:由于您要比较这些项的.Text属性,因此可以尝试使用LINQ将Text属性作为集合返回。然后,CollectionAssert将完全按照您的意愿工作,以比较Text的实际和预期集合。

答案 1 :(得分:0)

这里的问题可能与泛型无关,而是与实现2个列表的相等性有关。列表上的Equals()可以是Object实现,检查它是否只是相同的实例,而不是比较内容。

当我需要测试列表的内容已经按照预期使用C#和mbUnit填充时,我倾向于检查计数是否相等,然后检查列表中的每个项目。或者,如果我不关心结果列表中项目的顺序,我可以检查它是否包含每个项目。

Assert.AreEqual(3, result.Count);
Assert.Contains(expectedList[0], result);
Assert.Contains(expectedList[1], result);
Assert.Contains(expectedList[2], result);

修改

看起来像SelectListItem使用Object.Equals()实现,并且只检查引用相等(相同的实例)。我想到了两种解决方案。

  1. 编写一个方法来检查列表是否包含具有给定文本和值的项目,然后重用该项目。它有点干净,但不是很大,除非你有更多的测试。

  2. 使用linq语句从结果列表中选择所有文本和所有值。然后使用带有CollectionEquivalentConstraints的Asserts来检查列表是否相等。 (注意我自己没有对此进行过测试,并且正在使用在线文档)。

    var texts = result.Select(x =&gt; x.Text).ToList();
    var values = result.Select(x =&gt; x.Value).ToList();

    Assert.That(texts,Is.EquivalentTo(new string [] {expectedList [0] .Text,expectedList [1] .Text,...}); Assert.That(values,Is.EquivalentTo(new string [] {expectedList [0] .Value,expectedList [1] .Value,...});

  3. 您还可以通过将预期值生成为2个单独的列表来显着简化此操作。您可能还会生成Dictionary,并提供KeysValues作为等效列表。

答案 2 :(得分:0)

Dim i As Integer
    Assert.AreEqual(expected.Count, actual.Count)

    For i = 0 To expected.Count - 1
        Assert.AreEqual(expected.ToList.Item(i).ID, actual.ToList.Item(i).ID)
    Next

在这种情况下,我正在比较ID,我想你可以比较任何值类型的键字段并得到相同的。这传递了,而没有任何CollectionAssert方法对我有任何帮助。

Lisa Morgan