简体   繁体   English

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

[英]C# Unit Test Fails, even though AssertAreEqual appear to be equal

I have a unit test as follows: 我的单元测试如下:

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

And from the above code I have made the following class: 从上面的代码中,我创建了以下类:

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

I have run the test and I get the error: 我已经运行测试,但出现错误:

Message: AssertAreEqual failed.

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

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

Would someone be able to explain to me why this unit test is failing even though the Expected value == to the Actual value? 即使期望值==等于实际值,也有人可以向我解释为什么该单元测试失败了吗? And how would I fix it so that my unit test passes? 以及如何解决它,以便我的单元测试通过?

Two things you'll need to do, first use CollectionAssert.AreEqual and second, override the Equals and GetHashCode methods in the Guess class. 您需要做两件事,首先使用CollectionAssert.AreEqual ,其次,重写Guess类中的EqualsGetHashCode方法。

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

When printing out the "Expected" and "Actual" values, the test runner calls ToString() on the objects. 当打印出“ Expected”和“ Actual”值时,测试运行程序在对象上调用ToString() By default reference types print out the fully qualified type name, in your case: System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess] . 默认情况下,引用类型会打印出完全限定的类型名称,具体情况如下: System.Collections.Generic.List`1[Prigmore2013_01.Models.Guess]

You are confused because this prints out the same string in both cases; 您很困惑,因为这两种情况下都打印出相同的字符串。 this is because the two objects are instances of the same class (colloquially, List<Guess> ), which is why they print out the same identifying string. 这是因为这两个对象是同一类的实例(通常是List<Guess> ),这就是为什么它们打印出相同的标识字符串的原因。 But as others have pointed out, they are two different objects, stored in two different memory locations. 但是正如其他人指出的那样,它们是两个不同的对象,存储在两个不同的存储位置中。 Assert.AreEqual on reference types will perform "reference equality" -- not "is the content of these objects the same" but "are these two variables referencing the same memory location?" 引用类型上的Assert.AreEqual将执行“引用相等”-不是“这些对象的内容是否相同”,而是“这两个变量引用相同的内存位置吗?”

As others have pointed out, the .Net framework has a helpful tool to do what you're looking to do, compare the content of two lists ( CollectionAssert.AreEqual ); 正如其他人指出的那样,.Net框架提供了一个有用的工具来完成您想要做的事情,比较两个列表的内容( CollectionAssert.AreEqual )。 I just wanted to provide a little more background and address something that confused me when I was getting started. 我只是想提供更多背景知识,并解决一些让我入门时感到困惑的问题。

Look at what you're comparing in the assertion: 查看断言中要比较的内容:

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

expectedResult is the result of invoking theGame.ShowGuessesMade() , while result is the result of invoking controller.ShowPreviousGuesses() expectedResult是调用的结果theGame.ShowGuessesMade()result是调用的结果controller.ShowPreviousGuesses()

These are two different lists. 这是两个不同的列表。 Note that even though they both might be empty, or contain the same elements in the same order, that does not make them equal - equivalent , in a semantic sense, maybe - but not equal. 请注意,即使它们可能为空,或以相同的顺序包含相同的元素,也不会使它们相等-从语义上说, 等效 -也许-但不相等。 Equality in this case (for reference types) normally means "is this object the exact same object as this other object". 在这种情况下(对于引用类型),相等通常表示“此对象与另一个对象是完全相同的对象”。

As @MichaelPerrenoud said above, you'll want to use CollectionAssert.AreEqual when you're trying to assert equivalency of lists. 就像@MichaelPerrenoud上面说的那样,当您试图声明列表的等效性时,您将要使用CollectionAssert.AreEqual

Having not set up a constructor as follows: 尚未按如下方式设置构造函数:

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

I was returning a different instance of the object. 我正在返回该对象的另一个实例。 Having created a constructor I have being able to return the correct set of lists and in my controller I can then access the property directly: 创建构造函数后,我可以返回正确的列表集,然后在我的控制器中可以直接访问该属性:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM