我有一个单元测试如下:
[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]>.
有人能够向我解释为什么即使预期值==到实际值,此单元测试也会失败?我如何修复它以便我的单元测试通过?
答案 0 :(得分:4)
您需要做的两件事情,首先使用CollectionAssert.AreEqual
,然后覆盖Equals
类中的GetHashCode
和Guess
方法。
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);
}