Модульный Тест 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");

/* Что касается споров вокруг доступа к частным полям в модульных тестах, я считаю, что он никогда не должен использоваться, если это не абсолютно необходимо (т. е. вопросы управления временем и расходами). */