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

C#单元测试失败,即使AssertAreEqual看起来相等,c#,asp.net-mvc,unit-testing,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(); L

我有一个单元测试,如下所示:

[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);
}
 public GuessingGame()
        {
            //Set up the GuessingGame object
            this.Guesses = new List<Guess>();
        }
[TestMethod]
public void show previous guesses模型属性到存储在GuessingGameObject()中的ListFGUES对象
{
//安排
//首先,设置游戏并存储预期结果
var theGame=新猜游戏();
List expectedResult=theGame.showGuessMade();
//接下来,使用存储在会话中的此游戏设置FakeHttpContext
var theContext=new FakeHttpContext();
var theKey=“游戏状态”;
context.Session.Add(按键,游戏);
//现在,使用此上下文设置控制器
var控制器=新的Exercise09Controller();
var request=new System.Web.Routing.RequestContext(context,new System.Web.Routing.routedData());
controller.ControllerContext=new System.Web.Mvc.ControllerContext(请求,控制器);
//表演
var result=controller.ShowPreviousGuesses();
//断言
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;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web;
名称空间Prigmore2013_01.Models
{
公开课猜谜游戏
{
公共列表目标{get;set;}
公共列表猜测{get;set;}
公开列表showGuessMade()
{
var listRange=新列表();
如果(listRange!=null)
{
返回列表范围;
}
返回列表范围;
}
}
}
我已经运行了测试,我得到了错误:

Message: AssertAreEqual failed.

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

Actual:<System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess]>.
消息:AssertAreEqual失败。
预期:。
实际值:。

有人能给我解释一下为什么这个单元测试失败了,即使预期值==与实际值一致?我如何修复它以使我的单元测试通过?

您需要做两件事,第一件是使用,第二件是覆盖
Guess
类中的
Equals
GetHashCode
方法

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();
    }
}

您需要做两件事,第一件是使用,第二件是重写
Guess
类中的
Equals
GetHashCode
方法

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();
    }
}

看看您在断言中比较的内容:

//Assert
Assert.AreEqual(expectedResult, result.Model);
expectedResult
是调用
游戏的结果。ShowGuessMade()
,而
result
是调用
控制器的结果。ShowPreviousGuesses()

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


正如@MichaelPerrenoud在上面所说的,当您试图断言列表的等价性时,您需要使用
CollectionAssert.AreEqual

查看您在断言中比较的内容:

//Assert
Assert.AreEqual(expectedResult, result.Model);
expectedResult
是调用
游戏的结果。ShowGuessMade()
,而
result
是调用
控制器的结果。ShowPreviousGuesses()

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

正如@MichaelPerrenoud上面所说的,当您试图断言列表的等价性时,您需要使用
CollectionAssert.AreEqual

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

您感到困惑,因为这两种情况下打印出的字符串相同;这是因为这两个对象是同一个类的实例(通俗地说是
List
),这就是它们打印出相同标识字符串的原因。但正如其他人所指出的,它们是两个不同的对象,存储在两个不同的内存位置。引用类型上的Assert.AreEqual将执行“引用相等”——不是“这些对象的内容相同”,而是“这两个变量引用相同的内存位置吗?”

正如其他人所指出的那样,.Net framework有一个有用的工具来完成您想要做的事情,比较两个列表的内容(
CollectionAssert.AreEqual
);我只是想提供更多的背景知识,并解决一些在开始时让我感到困惑的问题。

当打印出“预期”和“实际”值时,测试运行程序对对象调用
ToString()
。默认情况下,引用类型打印出完全限定的类型名称,在您的示例中:
System.Collections.Generic.List`1[Prigmore2013\u 01.Models.Guess]

您感到困惑,因为这两种情况下打印出的字符串相同;这是因为这两个对象是同一个类的实例(通俗地说是
List
),这就是它们打印出相同标识字符串的原因。但正如其他人所指出的,它们是两个不同的对象,存储在两个不同的内存位置。引用类型上的Assert.AreEqual将执行“引用相等”——不是“这些对象的内容相同”,而是“这两个变量引用相同的内存位置吗?”


正如其他人所指出的那样,.Net framework有一个有用的工具来完成您想要做的事情,比较两个列表的内容(
CollectionAssert.AreEqual
);我只是想提供更多的背景知识,并解决一些在我刚开始时让我感到困惑的问题。

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

[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);
}
 public GuessingGame()
        {
            //Set up the GuessingGame object
            this.Guesses = new List<Guess>();
        }

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