Модульный Тест Assert.AreEqual не удалось
у меня есть модульный тест для метода, который получает объект из коллекции. Это продолжает терпеть неудачу, и я не могу понять, почему, поэтому я создал очень простой тест ниже, чтобы создать объект поставщика 2 и проверить, что они равны, чтобы увидеть, могу ли я определить проблему в моем тесте моего кода. Но этот тест снова провалился. Кто-нибудь может понять или объяснить почему?
[TestMethod()]
public void GetSupplierTest2()
{
Supplier expected = new Supplier();
expected.SupplierID = 32532;
expected.SupplierName = "Test 1"
Supplier actual = new Supplier();
actual.SupplierID = 32532;
actual.SupplierName = "Test 1"
Assert.AreEqual(expected, actual);
}
но если я проверяю отдельные свойства объектов, тест проходит...
[TestMethod()]
public void GetSupplierTest2()
{
Supplier expected = new Supplier();
expected.SupplierID = 32532;
expected.SupplierName = "Test 1"
Supplier actual = new Supplier();
actual.SupplierID = 32532;
actual.SupplierName = "Test 1"
Assert.AreEqual(expected.SupplierID , actual.SupplierID );
Assert.AreEqual(expected.SupplierName , actual.SupplierName );
}
6 ответов
если вы хотите сравнить два разных экземпляра поставщика и хотите, чтобы они считались равными, когда некоторые свойства имеют одинаковое значение, вы должны переопределить Equals
метод on Supplier
и сравните эти свойства в методе.
вы можете прочитать больше о методе Equals здесь:http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
пример реализации:
public override bool Equals(object obj)
{
if (obj is Supplier)
{
Supplier other = (Supplier) obj;
return Equals(other.SupplierID, this.SupplierID) && Equals(other.SupplierName, this.SupplierName);
}
return false;
}
обратите внимание, что вы также получите предупреждение компилятора что вы также должны реализовать GetHashCode, это может быть так просто:
public override int GetHashCode()
{
return SupplierID;
}
как и любой другой ответ, проблема в том, что вы пытаетесь сравнить экземпляры Supplier
[наверное] без переопределения Equals
метод. но я не думаю, что вы должны переопределить Equals
для тестирования так как это может повлиять на производство код или вам может понадобиться другой Equals
логика в производственном коде.
вместо этого вы должны либо утверждать каждый член по одному, как вы это делаете в первом примере (если у вас нет много мест, где вы хотите сравнить весь объекта) или инкапсулировать эту логику сравнения в класс и использовать этот класс:
static class SupplierAllFieldsComparer
{
public static void AssertAreEqual(Supplier expected, Supplier actual)
{
Assert.AreEqual(expected.SupplierID , actual.SupplierID );
Assert.AreEqual(expected.SupplierName , actual.SupplierName );
}
}
// тестовый код:
SupplierAllFieldsComparer.AssertAreEqual(expected, actual);
реализация по умолчанию Object.Equals
для ссылочных типов (т. е. классов) "равноправие": являются ли два объекта на самом деле то же самое экземпляра. Он не сравнивает значения полей.
либо (как показали другие) переопределить Equals
чтобы дать "равенство значений". В этом случае вы также должны переопределить GetHashCode
(поэтому контейнеры работают) и должны переопределять operator ==
.
альтернативно примите, что большинство сущностей должны иметь ссылочное равенство (два поставщики с одинаковым названием Не всегда являются одной и той же организацией) и фактически используют свойства напрямую.
вы сравниваете 2 разных экземпляра типа поставщика, поэтому Assert fail.
Если вы хотите, чтобы поставщик равны сказать (по их Id) можно переопределить равна метод, здесь очень за simpled примере :Д.
public class Supplier
{
private int id;
private string name;
public int Id
{
get { return id; }
}
public string Name
{
get { return name; }
}
public bool Equals(Supplier other)
{
if(other == null) return false;
return other.id == id;
}
public override bool Equals(object obj)
{
if(obj == null) return false;
if (obj.GetType() != typeof (Supplier)) return false;
return Equals((Supplier) obj);
}
public override int GetHashCode()
{
return id;
}
}
при тестировании отдельных свойств вы сравниваете строковые / целочисленные значения. Они равны,и поэтому испытания проходят.
при тестировании родительских объектов вы сравниваете только две контейнерные структуры типа поставщик - и даже если они могут иметь равные значения свойств, они не равны: поскольку вы создаете два отдельных объекта, они не находятся по одному адресу в памяти.
//Given the following structure and an instance value, targetObj...
class BaseType
{
private FeatureType Feature_1;
}
class TargetType : BaseType
{
...
}
TargetType targetObj = new TargetType();
//...a private feature in a specific base class can be accessed as follows
PrivateType typeCast = new PrivateType(typeof( BaseType ));
PrivateObject privateObj = new PrivateObject(targetObj, typeCast);
//...and values can be retrieved and set as follows....
privateObj.SetField("Feature_1", (FeatureType) newValue );
FeatureType result = (FeatureType) privateObj.GetField("Feature_1");
/* Что касается споров вокруг доступа к частным полям в модульных тестах, я считаю, что он никогда не должен использоваться, если это не абсолютно необходимо (т. е. вопросы управления временем и расходами). */