Модульный тест Assert.AreEqual не выполнен - PullRequest
10 голосов
/ 13 июня 2011

У меня есть модульный тест для метода, который получает объект из коллекции.Это продолжает давать сбой, и я не могу понять, почему, поэтому я создал очень простой тест ниже, чтобы создать 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 ]

22 голосов
/ 13 июня 2011

Как и в любом другом ответе, проблема в том, что вы пытаетесь сравнить экземпляры 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);
4 голосов
/ 13 июня 2011

Если вы хотите сравнить два разных экземпляра поставщика и хотите, чтобы они считались равными, когда определенные свойства имеют одинаковое значение, вы должны переопределить метод Equals для 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;
}
3 голосов
/ 13 июня 2011

Реализация по умолчанию Object.Equals для ссылочных типов (т. Е. Классов) - "Справочное равенство": это два объекта на самом деле один и тот же экземпляр.Он не сравнивает значения полей.

Либо (как показали другие) переопределить Equals, чтобы получить «равенство значений».В этом случае вы также должны переопределить GetHashCode (чтобы контейнеры работали) и переопределить operator ==.

В качестве альтернативы вы должны признать, что большинство организаций должны иметь ссылочное равенство (два поставщика с одинаковым именем не всегда являются одной и той же организацией) и фактически использовать свойства напрямую.

2 голосов
/ 13 июня 2011

Вы сравниваете 2 разных экземпляра типа «Поставщик», поэтому Assert терпит неудачу.

Если вы хотите, чтобы поставщик равнялся (по их Id ), вы можете переопределить метод Equals , здесь очень упрощенный пример: D.

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;
    } 
}
1 голос
/ 13 июня 2011

При тестировании отдельных свойств вы сравниваете строковые / целочисленные значения. Они равны, и поэтому испытания проходят.

При тестировании родительских объектов вы сравниваете только две контейнерные структуры типа Поставщик - и даже если они могут содержать равные значения свойств, они не равны: поскольку вы создаете экземпляры двух отдельных объектов, они не находятся в одном и том же месте. адрес в памяти.

0 голосов
/ 11 июля 2011
//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");

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

...