Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > NUnit сравнение объектов


Автор: mullih 3.8.2007, 10:51
Добрый день 
Начал изучать NUnit и столкнулся с такой проблемой. При проверке на равенство двух одинаковых объектов не выполняется тест
Код

namespace NUnit_Test {
    public class Dollar {
        public int amount;

        public Dollar(int amount) {
            this.amount = amount;
        }

    }

    [TestFixture]
    public class DollarTest {

        [Test]
        public void testMultiplication() {
            Dollar five = new Dollar(5);
            Assert.AreEqual(five, new Dollar(5));
        }
    }
}



Подскажите пожалуйста почему Assert.AreEqual(five, new Dollar(5)); выкидывает исключение?

Автор: anonym 3.8.2007, 11:34
Не знаю, что такое NUnit, но есть предположение, что Assert.AreEqual для ссылочных типов сравнивает адреса объектов в памяти. Очевидно, второй созданный обхект new Dollar(5) расположени уже совсем не там, где первый.

Автор: andrx 3.8.2007, 11:42
anonym 
поддерживаю

mullih 
посмотри http://msdn2.microsoft.com/en-us/library/ms243413(VS.80).aspx

Автор: mihryak 3.8.2007, 11:54
если хочешь, чтобы экземпляры сравнивались по свойству amount заоверрайдь метод Equals() в классе Dollar.
Код

            public override bool Equals(object obj)
            {
                if (!(obj is Dollar))
                {
                    return false;
                }

                return ((Dollar)obj).amount == amount;
            }

Автор: mullih 3.8.2007, 12:01
Спасибо за помощь 
На самом деле надо было переопределить Equals
Сам не подумал что AreEqual привязана к этому методу класса
Тему можно закрывать

Автор: Wizard_Memfis 6.8.2007, 11:19
Также можно без переопределения метода сравнить самому поля этих объектов!Тогда твой код будет без изменений!Это уже кому как нравится! smile 

Автор: Naum 6.8.2007, 13:23
Цитата(Wizard_Memfis @  6.8.2007,  12:19 Найти цитируемый пост)
Это уже кому как нравится!

Я бы сказал зависит от нужд приложения. У юнит-тестирования есть одна проблемка: иногда код приложения начинают писать, чтобы только тесты не падали.
Если тебе не надо переопределять Equals, то и не надо делать это ради тестов, а лучше 
Цитата(Wizard_Memfis @  6.8.2007,  12:19 Найти цитируемый пост)
без переопределения метода сравнить самому поля этих объектов

Если же ты намереваешься где-либо еще, кроме тестов, пользоваться этим методом, тогда, конечно, надо переопределить. smile

Автор: mihryak 6.8.2007, 13:27
Wizard_Memfis, не лучший вариант, при любом изменении критериев сравнения их придётся искать по всему коду и править, а так в Equals всё локализовано.
Если поле для сравнения нужно не одно (чаще всё же одно, нечто вроде идентификатора), а все свойства, то можно в тот же Equals написать так, чтобы он все эти свойства вытаскивал через рефлексию. Это даст возможность не переписывать Equals после каждого изменения списка свойств.

Ещё можно переопределить оператор ==, что может дать дополнительные удобства при написании кода.

Автор: mullih 7.8.2007, 12:04
Цитата(mihryak @ 6.8.2007,  13:27)
Если поле для сравнения нужно не одно (чаще всё же одно, нечто вроде идентификатора), а все свойства, то можно в тот же Equals написать так, чтобы он все эти свойства вытаскивал через рефлексию. Это даст возможность не переписывать Equals после каждого изменения списка свойств.

А можно привести маленький пример как свойства вытаскивать через рефлексию 
У меня получилось найти только public поля 

Автор: mihryak 7.8.2007, 12:30
в параметр BindingFlags добавь BindingFlags.NonPublic

Автор: mihryak 7.8.2007, 12:47
Код

    public class PropertiesTestClass
    {
        private string privateStringValue = "private";
        private string publicStringValue = "public";

        private string PrivateStringValue
        {
            get { return privateStringValue; }
            set { privateStringValue = value; }
        }

        public string PublicStringValue
        {
            get { return publicStringValue; }
            set { publicStringValue = value; }
        }
    }

    public static void Main()
    {
        PropertiesTestClass test = new PropertiesTestClass();

        PropertyInfo[] propertiesInfo =
            test.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);

        foreach (PropertyInfo propertyInfo in propertiesInfo)
        {
            Console.WriteLine(propertyInfo.Name);
            Console.WriteLine(test.GetType().InvokeMember(propertyInfo.Name,
               BindingFlags.Public | BindingFlags.NonPublic |
               BindingFlags.Instance | BindingFlags.GetProperty,
               null, test, null));
        }

        Console.ReadKey();
    }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)