В чем разница между Assert.AreNotEqual и Assert.AreNotSame?
В C# какая разница между
Assert.AreNotEqual
а также
Assert.AreNotSame
6 ответов
Почти все ответы, приведенные здесь, верны, но, вероятно, стоит привести пример:
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 на string, AreSame и AreEqual будут возвращать одно и то же значение.
полностью зависит от того, как переменные инициализируются. Если они используют строковые литералы, тогда интернирование позаботится об этом. Однако, если вы используете:
string firstString = 1.ToString();
string secondString = 1.ToString();
тогда AreSame и AreEqual почти наверняка не вернут одно и то же значение.
Что касается:
Общее правило - использовать AreEqual для типов значений и AreSame для ссылочных типов.
Я почти никогда не хочу проверять идентификационные данные. Это редко полезно для меня. Я хочу проверить на эквивалентность, которая является то, что AreEqual
проверяет на. (Я не говорю, что AreSame
не должно быть там - это полезный метод, просто гораздо реже, чем AreEqual
.)
Две вещи могут быть равны, но разные объекты. AreNotEqual проверяет значения объектов с помощью теста на равенство, а AreNotSame проверяет, что они не являются точными объектами.
Понятно, почему мы хотели бы проверить эти вещи AreNotEqual (мы заботимся о тестируемых значениях); как насчет AreNotSame? Полезность этого в тестировании обнаруживается, когда вы передали ссылки и хотите убедиться, что после того, как ваша перетасовка завершена, две ссылки остаются одним и тем же объектом.
В реальных условиях мы используем множество объектов кэширования для уменьшения количества обращений к базе данных. После того, как объект был передан в систему кеша, наши модульные тесты гарантируют, что в некоторых случаях мы возвращаем тот же объект (кэш был действителен), а в других случаях мы возвращаем свежий объект (кеш был признан недействительным). Обратите внимание, что в этом случае AreNotEqual не обязательно будет достаточным. Если у объекта была новая временная метка в базе данных, но данные не были "достаточно разными", чтобы не пройти тест на равенство, AreNotEqual не заметил бы, что мы обновили объект.
AreNotSame выполняет сравнение ссылок, тогда как AreNotEqual выполняет сравнение на равенство.
Assert.AreNotEqual утверждает, что два значения не равны друг другу.
Assert.AreNotSame утверждает, что две переменные не указывают на один и тот же объект.
Пример 1:
int i = 1; int j = i; // Значения равны: Assert.AreEqual(i, j); // Два типа значений * не * представляют один и тот же объект: Assert.AreNotSame(i, j);
Пример 2:
строка s = "A"; строка t = s; // Значения равны: Assert.AreEqual(s, t); // Ссылочные типы * могут * указывать на один и тот же объект: Assert.AreSame(s, t);
AreNotSame использует равенство ссылок (object.ReferenceEquals
) - т.е. являются ли они одним и тем же действительным экземпляром объекта; AreNotEqual использует концептуальное равенство (.Equals
) - то есть они считаются равными.
Разве это не так, что AreNotEqual проверяет случай, когда два объекта не равны с точки зрения метода Equals(), тогда как AreNotSame проверяет случай, когда две ссылки на объекты не совпадают. Таким образом, если x и y - два объекта, которые равны с точки зрения Equals(), но были выделены отдельно, то AreNotEqual() вызовет ошибочное утверждение, а другой - нет.