NUnit не работает с Assert.AreEqual
Я новичок в модульном тестировании и в частности NUit.
Я просто набираю несколько примеров из книги, которая относится к Java и JUnit. Но вместо этого я использую С#.
Проблема в том, что у меня есть класс с переопределенными методами, такими как Equals()
и GetHashCode()
, но когда я пытаюсь сравнить два объекта этого класса с Assert.AreEqual()
, мой код не вызывается, поэтому я получить исключение.
Assert.True(MyClass.Equals(MyClass2))
работает хорошо. Но я не хочу использовать эту конструкцию вместо Assert.AreEqual()
. Где может быть проблема?
Вот класс:
public class Money
{
public int amount;
protected string currency;
public Money(int amount, string currency)
{
this.amount = amount;
this.currency = currency;
}
public new bool Equals(object obj)
{
if (obj == null)
return false;
Money money = (Money)obj;
return (amount == money.amount)
&& (Currency().Equals(money.Currency()));
}
public new int GetHashCode()
{
return (string.Format("{0}{1}", amount, currency)).GetHashCode();
}
public static Money Dollar(int amount)
{
return new Money(amount, "USD");
}
public static Money Franc(int amount)
{
return new Money(amount, "CHF");
}
public Money Times(int multiplier)
{
return new Money(amount * multiplier, currency);
}
public string Currency()
{
return currency;
}
}
И сам метод тестирования:
[TestFixture]
public class DollarTest
{
[Test]
public void TestMultiplication()
{
Money five = Money.Dollar(5);
Assert.True(Money.Dollar(10).Equals(five.Times(2))); // ok
Assert.AreEqual(Money.Dollar(10), five.Times(2)); // fails
}
}
Ответы
Ответ 1
Проблема в том, что вы скрываете Equals, а не переопределяете ее. Молодцы - ваш unit test нашел ошибку:)
Ваш код должен быть:
public override bool Equals(object obj)
{
Money money = obj as Money;
if (money == null)
return false;
return (amount == money.amount && currency == money.currency);
}
(Это предотвратит его отбрасывание исключения, если вы также присвоите ему неправильный тип.)
Я также упростил проверку равенства строк - перегрузка оператора может быть очень полезной:)
Кстати, вы почти наверняка хотите:
- Измените
Currency
как свойство, а не метод
- Добавить свойство
Amount
- Вероятно, измените тип
Amount
на decimal
вместо int
- Сделать поля приватными и readonly
- Запечатать класс
- Добавить перегрузки операторов для == и!=
- Возможно, добавлена перегрузка оператора *, чтобы сделать то же самое, что и
Times
- Избегайте форматирования строк при вычислении хэша (есть десятки ответов, показывающих лучшие реализации хэша)
EDIT: Я только перечитал, что вы используете пример из книги. Действительно ли книга скрывается вместо переопределения метода Equals
? Я предлагаю вам получить новую книгу, если да (если это не преднамеренный пример того, когда неправильно использовать скрытие!)... в какой книге?
Ответ 2
Я сбив с толку, что реализация интерфейса IEquatable, которая также имеет
Equals(T other)
поставил меня с той же проблемой, как описано выше.
Единственная причина, по которой я решил использовать интерфейс IEquaytable выше переопределения метода Equals, не должен был делать проверку типа.
В конце концов мне пришлось использовать следующий код
public bool Equals(CustomTag other)
{
return (other.Name.Trim().ToLower() == Name.Trim().ToLower());
}
public override bool Equals(object o)
{
if (o is CustomTag)
{
return Equals(o as CustomTag);
}
return false;
}
но потом я подумал, почему бы просто не оставить интерфейс IEquatable для того, что он есть, и только переопределить метод Equals. (меньше кода = лучше)
Ответ 3
Я подозреваю, что ваша проблема в том, что вы не перегружали , чтобы перегрузить оператор равенства ==. Под капотом Assert.AreEqual, вероятно, использует ==.
См. Учебное пособие по перегрузке оператора.
Обновление: я проверил тест NUnit через отладчик, и он действительно использует метод Equals, а не оператор ==.
Ответ 4
Вы можете написать утверждения агностики фреймов, используя библиотеку с именем Should. Он также имеет очень хороший плавный синтаксис, который можно использовать, если вам нравятся плавные интерфейсы. У меня была запись в блоге, связанная с тем же.
http://nileshgule.blogspot.com/2010/11/use-should-assertion-library-to-write.html