Какая разница между Assert.AreNotEqual и Assert.AreNotSame?

В С#, какая разница между

Assert.AreNotEqual

и

Assert.AreNotSame

Ответ 1

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

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.)

Ответ 2

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

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

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

Ответ 3

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

Ответ 4

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);

Ответ 5

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

Ответ 6

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