В чем разница между Assert.AreNotEqual и Assert.AreNotSame? - PullRequest
60 голосов
/ 13 февраля 2009

В C #, в чем разница между

Assert.AreNotEqual

и

Assert.AreNotSame

Ответы [ 6 ]

81 голосов
/ 13 февраля 2009

Почти все ответы, приведенные здесь, верны, но, вероятно, стоит привести пример:

public static string GetSecondWord(string text)
{
    // Yes, an appalling implementation...
    return text.Split(' ')[1];
}

string expected = "world";
string actual = GetSecondWord("hello world");

// Good: the two strings should be *equal* as they have the same contents
Assert.AreEqual(expected, actual);

// Bad: the two string *references* won't be the same
Assert.AreSame(expected, actual);

AreNotEqual и AreNotSame - это, конечно, инверсии AreEqual и AreSame.

РЕДАКТИРОВАТЬ: опровержение в настоящее время принятый ответ ...

Если вы используете Assert.AreSame с типами значений, они помещаются в квадрат. Другими словами, это эквивалентно выполнению:

int firstNumber = 1;
int secondNumber = 1;
object boxedFirstNumber = firstNumber;
object boxedSecondNumber = secondNumber;

// There are overloads for AreEqual for various value types
// (assuming NUnit here)
Assert.AreEqual(firstNumber, secondNumber);

// ... but not for AreSame, as it's not intended for use with value types
Assert.AreSame(boxedFirstNumber, boxedSecondNumber);

Ни firstNumber, ни secondNumber не имеют значения объекта, поскольку int является типом значения. Причина, по которой вызов AreSame не удастся, заключается в том, что в .NET при упаковке значения каждый раз создается новое поле. (В Java это иногда не так - меня это уже поразило.)

Как правило, никогда не следует использовать AreSame при сравнении типов значений. Когда вы сравниваете ссылки типов, используйте AreSame, если вы хотите проверить идентичные ссылки; используйте AreEqual, чтобы проверить эквивалентность в Equals. РЕДАКТИРОВАТЬ: Обратите внимание, что бывают ситуации, когда NUnit не просто использует Equals напрямую; в него встроена поддержка коллекций, где элементы в коллекциях проверяются на равенство.

Претензия в ответе:

Используя приведенный выше пример изменения int в строку, AreSame и AreEqual вернет то же значение.

полностью зависит от того, как инициализируются переменные. Если они используют строковые литералы, тогда интернирование позаботится об этом. Однако, если вы используете:

string firstString = 1.ToString();
string secondString = 1.ToString();

тогда AreSame и AreEqual почти наверняка не вернут одно и то же значение.

Что касается:

Общее правило - использовать AreEqual для типов значений и AreSame для ссылочные типы.

Я почти никогда хочу проверить идентификационные данные. Это редко полезно для меня. Я хочу проверить эквивалентность , что AreEqual проверяет. (Я не говорю, что AreSame не должно быть там - это полезный метод, просто гораздо реже, чем AreEqual.)

25 голосов
/ 13 февраля 2009

Две вещи могут быть равны, но разные объекты. AreNotEqual проверяет объекты значения с помощью теста на равенство, в то время как AreNotSame проверяет, что они не являются точными объектами.

Очевидно, что мы хотели бы проверить эти вещи AreNotEqual (мы заботимся о тестируемых значениях); как насчет AreNotSame? Полезность этого в тестировании обнаруживается, когда вы передали ссылки вокруг и хотите убедиться, что после того, как ваша перетасовка завершена, две ссылки остаются одним и тем же объектом.

В реальных условиях мы используем множество объектов кэширования для уменьшения количества обращений к базе данных. После того, как объект был передан в систему кеша, наши модульные тесты гарантируют, что в некоторых случаях мы возвращаем один и тот же объект (кэш был действительным), а в других случаях мы возвращаем объект fresh (кэш был аннулированный). Обратите внимание, что AreNotEqual не обязательно будет достаточным в этом случае. Если бы у объекта была новая отметка времени в базе данных, но данные не были «достаточно разными», чтобы не пройти тест на равенство, AreNotEqual не заметил бы, что мы обновили объект .

19 голосов
/ 13 февраля 2009

AreNotSame выполняет сравнительное сравнение, тогда как AreNotEqual выполняет сравнение на равенство.

8 голосов
/ 13 февраля 2009

Assert.AreNotEqual утверждает, что два значения не равны друг другу.

Assert.AreNotSame утверждает, что две переменные не указывают на один и тот же объект.

Пример 1:

int i = 1;
int j = i;
// The values are equal:
Assert.AreEqual(i, j);
// Two value types do *not* represent the same object:
Assert.AreNotSame(i, j);

Пример 2:

string s = "A";
string t = s;
// The values are equal:
Assert.AreEqual(s, t);
// Reference types *can* point to the same object:
Assert.AreSame(s, t);
7 голосов
/ 13 февраля 2009

AreNotSame использует равенство ссылок (object.ReferenceEquals) - то есть они являются одним и тем же фактическим экземпляром объекта; AreNotEqual использует концептуальное равенство (.Equals) - т.е. они считаются равными.

3 голосов
/ 13 февраля 2009

Не правда ли, что AreNotEqual проверяет случай, когда два объекта не равны с точки зрения метода Equals (), тогда как AreNotSame проверяет случай, когда две ссылки на объекты не совпадают. Поэтому, если x и y - два объекта, которые равны с точки зрения Equals (), но были выделены отдельно, AreNotEqual () вызовет ошибочное утверждение, а другой - нет.

...