Сравните равенство между двумя объектами в NUnit

118
задан Julian 13 November 2018 в 14:57
поделиться

4 ответа

Переопределите.Equals для своего объекта, и в модульном тесте можно тогда просто сделать это:

Assert.AreEqual(LeftObject, RightObject);

, Конечно, это могло бы означать, что Вы просто перемещаете все отдельные сравнения с.Equals методом, но он позволил бы Вам снова использовать ту реализацию для нескольких тестов, и вероятно имеет смысл иметь, если объекты должны быть в состоянии сравнить себя с одноуровневыми элементами так или иначе.

48
ответ дан angry person 24 November 2019 в 01:52
поделиться

Я предпочитаю не переопределять, Равняется только, чтобы позволить тестировать. Не забывайте, что, если Вы действительно переопределяете, Равняется Вам, действительно должен переопределить GetHashCode также, или можно получить неожиданные результаты при использовании объектов в словаре, например.

мне действительно нравится отражательный подход выше, поскольку он обслуживает добавление свойств в будущем.

Для быстрого и простого решения однако его часто самый легкий или создать вспомогательный метод, который тестирует, если объекты равны, или реализуют IEqualityComparer на классе, Вы сохраняете частными к своим тестам. При использовании решения IEqualityComparer Вы не должны беспокоиться реализацией GetHashCode. Например:

// Sample class.  This would be in your main assembly.
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// Unit tests
[TestFixture]
public class PersonTests
{
    private class PersonComparer : IEqualityComparer<Person>
    {
        public bool Equals(Person x, Person y)
        {
            if (x == null && y == null)
            {
                return true;
            }

            if (x == null || y == null)
            {
                return false;
            }

            return (x.Name == y.Name) && (x.Age == y.Age);
        }

        public int GetHashCode(Person obj)
        {
            throw new NotImplementedException();
        }
    }

    [Test]
    public void Test_PersonComparer()
    {
        Person p1 = new Person { Name = "Tom", Age = 20 }; // Control data

        Person p2 = new Person { Name = "Tom", Age = 20 }; // Same as control
        Person p3 = new Person { Name = "Tom", Age = 30 }; // Different age
        Person p4 = new Person { Name = "Bob", Age = 20 }; // Different name.

        Assert.IsTrue(new PersonComparer().Equals(p1, p2), "People have same values");
        Assert.IsFalse(new PersonComparer().Equals(p1, p3), "People have different ages.");
        Assert.IsFalse(new PersonComparer().Equals(p1, p4), "People have different names.");
    }
}
34
ответ дан Bobby Cannon 24 November 2019 в 01:52
поделиться

Если Вы не можете переопределить, Равняется по любой причине, можно создать вспомогательный метод, который выполняет итерации через общественные собственности отражением, и утверждайте каждое свойство. Что-то вроде этого:

public static class AssertEx
{
    public static void PropertyValuesAreEquals(object actual, object expected)
    {
        PropertyInfo[] properties = expected.GetType().GetProperties();
        foreach (PropertyInfo property in properties)
        {
            object expectedValue = property.GetValue(expected, null);
            object actualValue = property.GetValue(actual, null);

            if (actualValue is IList)
                AssertListsAreEquals(property, (IList)actualValue, (IList)expectedValue);
            else if (!Equals(expectedValue, actualValue))
                Assert.Fail("Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue);
        }
    }

    private static void AssertListsAreEquals(PropertyInfo property, IList actualList, IList expectedList)
    {
        if (actualList.Count != expectedList.Count)
            Assert.Fail("Property {0}.{1} does not match. Expected IList containing {2} elements but was IList containing {3} elements", property.PropertyType.Name, property.Name, expectedList.Count, actualList.Count);

        for (int i = 0; i < actualList.Count; i++)
            if (!Equals(actualList[i], expectedList[i]))
                Assert.Fail("Property {0}.{1} does not match. Expected IList with element {1} equals to {2} but was IList with element {1} equals to {3}", property.PropertyType.Name, property.Name, expectedList[i], actualList[i]);
    }
}
116
ответ дан Noctis 24 November 2019 в 01:52
поделиться

Я согласен с ChrisYoxall - реализация Equals в вашем основном коде исключительно для целей тестирования не годится.

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

Короче говоря, держите код только для тестирования вне своего класса.

Простого поверхностного сравнения свойств с использованием отражения должно быть достаточно для большинства классов, хотя вам может потребоваться повторение, если ваши объекты имеют сложные свойства. Если вы следите за ссылками, остерегайтесь циркулярных ссылок или аналогичных.

Хитрый

9
ответ дан 24 November 2019 в 01:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: