В С#, какая разница между
Assert.AreNotEqual
и
Assert.AreNotSame
В С#, какая разница между
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
, конечно.
EDIT: опровержение принятого в настоящее время ответа...
Если вы используете 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 not intended for use with value types
Assert.AreSame(boxedFirstNumber, boxedSecondNumber);
Ни firstNumber
, ни secondNumber
не имеет значения объекта, потому что int
- тип значения. Причина, по которой вызов AreSame
завершится неудачей, заключается в том, что в .NET бокс-значение каждый раз создает новый ящик. (В Java иногда это не так - это меня уже укусило.)
В основном вы никогда не должны использовать AreSame
при сравнении типов значений. Когда вы сравниваете типы ссылок, используйте AreSame
, если вы хотите проверить идентичные ссылки; используйте AreEqual
для проверки эквивалентности в Equals
. EDIT: Обратите внимание, что есть ситуации, когда NUnit не просто использует Equals
напрямую; он имеет встроенную поддержку коллекций, где элементы в коллекциях проверяются на равенство.
Требование в ответ, что:
Используя приведенный выше пример, изменив int to string, AreSame и AreEqual вернет то же значение.
полностью зависит от того, как инициализируются переменные. Если они используют строковые литералы, то, тем не менее, интернинг позаботится об этом. Если, однако, вы используете:
string firstString = 1.ToString();
string secondString = 1.ToString();
то AreSame и AreEqual почти наверняка не вернут одно и то же значение.
Что касается:
Общим правилом является использование AreEqual по типам значений и AreSame on ссылочные типы.
Я почти никогда не хочу проверять ссылочную идентификацию. Мне это редко бывает полезно. Я хочу проверить эквивалентность, что проверяет AreEqual
. (Я не говорю, что AreSame
не должно быть там - это полезный метод, гораздо реже, чем AreEqual
.)
Две вещи могут быть равны, но разные объекты. AreNotEqual проверяет значения объектов через тест равенства, в то время как AreNotSame проверяет, что они не точный точный объект.
Очевидно, почему мы хотели бы проверить, что вещи AreNotEqual (мы заботимся о тестируемых значениях); как насчет AreNotSame? Полезность этого в тестировании обнаруживается, когда вы проходили ссылки вокруг и хотите убедиться, что после того, как ваша перетасовка сделана, что две ссылки остаются одним и тем же объектом.
В реальном мире мы используем множество объектов кеширования для уменьшения округленных посещений базы данных. После того, как объект был передан в систему кеша, наши модульные тесты гарантируют, что в некоторых случаях мы возвращаем один и тот же объект (кеш был действителен), а в других случаях мы возвращаем новый объект (кеш был недействителен). Обратите внимание, что в этом случае в этом случае недостаточно данных AreNotEqual. Если у объекта была новая метка времени в базе данных, но данные не были "достаточно разными", чтобы не выполнить тест равенства, AreNotEqual не заметил бы, что мы обновили объект.
AreNotSame выполняет сравнение ссылок, тогда как AreNotEqual сравнивает равенство.
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);
AreNotSame использует ссылочное равенство (object.ReferenceEquals
) - то есть они являются одним и тем же фактическим экземпляром объекта; AreNotEqual использует концептуальное равенство (.Equals
) - то есть считаются равными.
Не так ли, что AreNotEqual проверяет случай, когда два объекта не равны в терминах метода Equals(), тогда как AreNotSame проверяет, где две ссылки на объекты не совпадают. Поэтому, если x и y - два объекта, которые равны в терминах Equals(), но были выделены отдельно, AreNotEqual() будет вызывать неудачное утверждение, а другое нет.