В чем разница между Assert.Равны и Assert.Одинаковы?
-
23-08-2019 - |
Вопрос
В C #, в чем разница между
Assert.AreNotEqual
и
Assert.AreNotSame
Решение
Почти все приведенные здесь ответы верны, но, вероятно, стоит привести пример:
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
.)
Другие советы
Две вещи могут быть равными, но разными объектами.AreNotEqual проверяет объекты ценности с помощью теста на равенство, в то время как AreNotSame проверяет, что они не являются одним и тем же точным объектом.
Очевидно, почему мы хотели бы проверить, что вещи не равны (мы заботимся о тестируемых значениях);а как насчет AreNotSame?Полезность этого при тестировании обнаруживается, когда вы передаете ссылки по кругу и хотите убедиться, что после завершения перетасовки две ссылки по-прежнему являются одним и тем же объектом.
В реальном случае мы используем множество объектов кэширования, чтобы уменьшить циклический доступ к базе данных.После того, как объект был передан в систему кэширования, наши модульные тесты гарантируют, что в некоторых случаях мы получаем обратно тот же объект (кэш был действительным), а в других случаях мы получаем обратно свежий объект (кэш был признан недействительным).Обратите внимание, что AreNotEqual в этом случае было бы необязательно достаточным.Если у объекта была новая временная метка в базе данных, все же данные был недостаточно "другим", чтобы провалить тест на равенство, AreNotEqual не заметил бы, что мы обновили объект.
Это одно и то же выполняет ссылочное сравнение, тогда как Не равны выполняет сравнение на равенство.
Утверждать.AreNotEqual утверждает, что два значения не равны друг другу.
Утверждать.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);
AreNotSame использует ссылочное равенство (object.ReferenceEquals
) - т. е.являются ли они одним и тем же фактическим экземпляром объекта;AreNotEqual использует концептуальное равенство (.Equals
) - т. е.являются ли они рассмотренный равный.
Разве это не так, что AreNotEqual проверяет случай, когда два объекта не равны с точки зрения метода Equals(), тогда как AreNotSame проверяет случай, когда две ссылки на объекты не совпадают.Таким образом, если x и y - это два объекта, которые равны с точки зрения Equals(), но были выделены отдельно, AreNotEqual() вызовет ошибочное утверждение, а другое - нет.