C#单元测试失败,即使AssertAreEqual看起来相等

时间:2013-12-09 14:38:04

标签: c# asp.net-mvc unit-testing

我有一个单元测试如下:

[TestMethod]
public void ShowPreviousGuessesSetsTheModelPropertyToTheListOfGuessObjectsStoredInTheGuessingGameObject()
{
    //Arrange
    //First, set up a game and store the expected result
    var theGame = new GuessingGame();
    List<Guess> expectedResult = theGame.ShowGuessesMade();
    //Next, set up a FakeHttpContext with this game stored in the Session
    var theContext = new FakeHttpContext();
    var theKey = "GameState";
    theContext.Session.Add(theKey, theGame);
    //Now, set up a controller with this context
    var controller = new Exercise09Controller();
    var request = new System.Web.Routing.RequestContext(theContext, new System.Web.Routing.RouteData());
    controller.ControllerContext = new System.Web.Mvc.ControllerContext(request, controller);

    //Act
    var result = controller.ShowPreviousGuesses();

    //Assert
    Assert.AreEqual(expectedResult, result.Model);
}

从上面的代码我做了以下课程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Prigmore2013_01.Models
{
    public class GuessingGame
    {

        public List<int> Target { get; set; }
        public List<int> Guesses { get; set; }

        public List<Guess> ShowGuessesMade()
        {
            var listRange = new List<Guess>();

            if (listRange != null)
            {
                return listRange;
            }
                return listRange;
        }
    }
}

我已经运行了测试,但我得到了错误:

Message: AssertAreEqual failed.

Expected:<System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess]>.

Actual:<System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess]>.

有人能够向我解释为什么即使预期值==到实际值,此单元测试也会失败?我如何修复它以便我的单元测试通过?

4 个答案:

答案 0 :(得分:4)

您需要做的两件事情,首先使用CollectionAssert.AreEqual,然后覆盖Equals类中的GetHashCodeGuess方法。

public class Guess
{
    ...

    public override bool Equals(object obj)
    {
        // determine equality
    }

    public override int GetHashCode()
    {
        // if you have an INT primary key here, it would be good to use that
        // Example: return this.IntProperty.GetHashCode();
    }
}

答案 1 :(得分:1)

当打印出“预期”和“实际”值时,测试运行器会在对象上调用ToString()。默认情况下,引用类型会打印出完全限定的类型名称,例如:System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess]

你很困惑,因为在这两种情况下都打印出相同的字符串;这是因为这两个对象是同一个类的实例(通俗地说,List<Guess>),这就是为什么它们打印出相同的标识字符串。但正如其他人所指出的那样,它们是两个不同的对象,存储在两个不同的存储位置。参考类型的Assert.AreEqual将执行“引用相等” - 而不是“这些对象的内容是否相同”,但“这两个变量是否引用相同的内存位置?”

正如其他人所指出的,.Net框架有一个有用的工具来完成你想要做的事情,比较两个列表的内容(CollectionAssert.AreEqual);我只是想提供一些背景知识,并解决一些让我困惑的事情。

答案 2 :(得分:0)

看看你在断言中所做的比较:

//Assert
Assert.AreEqual(expectedResult, result.Model);

expectedResult是调用theGame.ShowGuessesMade()的结果,而result是调用controller.ShowPreviousGuesses()的结果

这是两个不同的列表。请注意,即使它们都可能为空,或者包含相同顺序的相同元素,但这并不能使它们相等 - 等效,从语义上讲,可能 - 但不相等。在这种情况下的平等(对于引用类型)通常意味着“此对象是与该其他对象完全相同的对象”。

正如@MichaelPerrenoud上面所说,当你试图断言列表的等效性时,你会想要使用CollectionAssert.AreEqual

答案 3 :(得分:0)

没有按如下方式设置构造函数:

 public GuessingGame()
        {
            //Set up the GuessingGame object
            this.Guesses = new List<Guess>();
        }

我正在返回该对象的另一个实例。创建了一个构造函数后,我能够返回正确的列表集,然后在我的控制器中,我可以直接访问该属性:

public ViewResult ShowPreviousGuesses()
        {
    GuessingGame theGame = this.Session["GameState"] as GuessingGame;

    return View("Index", theGame.Guesses); 
}