En C #, quelle est la différence entre
Assert.AreNotEqual
et
Assert.AreNotSame
Presque toutes les réponses données ici sont correctes, mais cela vaut probablement la peine de donner un exemple:
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
et AreNotSame
ne sont que des inversions de AreEqual
et AreSame
bien sûr.
EDIT: Une réfutation à la réponse actuellement acceptée ...
Si tu utilises Assert.AreSame
avec des types valeur, ils sont encadrés. En d'autres termes, cela équivaut à faire:
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);
Ni firstNumber
ni secondNumber
n'ont de valeur d'objet, car int
est un type valeur. La raison pour laquelle l'appel AreSame
échouera est que dans .NET, la mise en boîte d'une valeur crée une nouvelle boîte à chaque fois. (Dans Java ce n'est parfois pas le cas - cela m'a déjà surpris.)
Fondamentalement, vous ne devriez jamais utiliser AreSame
lorsque vous comparez des types de valeur. Lorsque vous comparez des types référence , utilisez AreSame
si vous voulez vérifier les références identiques; utilisez AreEqual
pour vérifier l'équivalence sous Equals
. EDIT: Notez qu'il existe des situations où NUnit n'utilise pas simplement Equals
directement; il a un support intégré pour les collections, où les éléments des collections sont testés pour l'égalité.
L'affirmation dans la réponse que:
En utilisant l'exemple ci-dessus en changeant l'int en chaîne, AreSame et AreEqual renverront la même valeur.
dépend entièrement de la manière dont les variables sont initialisées. S'ils utilisent des chaînes littérales, alors encore, l'internement s'en chargera. Si, cependant, vous utilisez:
string firstString = 1.ToString();
string secondString = 1.ToString();
alors AreSame et AreEqual renverront presque certainement pas la même valeur.
Pour ce qui est de:
La règle générale consiste à utiliser AreEqual sur les types valeur et AreSame sur les types référence.
Je ne veux presque jamais vérifier l'identité de référence. Cela m'est rarement utile. Je veux vérifier l'équivalence qui est ce que AreEqual
vérifie. (Je ne dis pas que AreSame
ne devrait pas être là - c'est une méthode utile, juste beaucoup plus rarement que AreEqual
.)
Deux choses peuvent être égales, mais des objets différents. AreNotEqual vérifie les objets valeurs via le test d'égalité, tandis que AreNotSame vérifie qu'ils ne sont pas exactement le même objet.
Il est évident pourquoi nous voudrions tester que les choses ne sont pas égales (nous nous soucions des valeurs testées); qu'en est-il d'AreNotSame? L'utilité de ceci dans les tests se trouve lorsque vous avez passé des références et que vous voulez vous assurer qu'après la lecture aléatoire, deux références sont toujours le même objet.
Dans un cas réel, nous utilisons beaucoup d'objets de mise en cache pour atténuer les allers-retours vers la base de données. Après qu'un objet a été remis au système de cache, nos tests unitaires garantissent que dans certains cas, nous récupérons le même objet (le cache était valide) et dans d'autres cas, nous récupérons un frais objet (cache a été invalidé). Notez qu'AreNotEqual ne suffirait pas nécessairement dans ce cas. Si l'objet avait un nouvel horodatage dans la base de données, mais que data n'était pas "suffisamment différent" pour échouer un test d'égalité, AreNotEqual ne remarquerait pas que nous avons actualisé le object .
AreNotSame fait une comparaison de référence, tandis que AreNotEqual fait une comparaison d'égalité.
Assert.AreNotEqual affirme que deux valeurs ne sont pas égales l'une à l'autre.
Assert.AreNotSame affirme que deux variables ne pointent pas vers le même objet.
Exemple 1:
int i = 1; int j = i; // Les valeurs sont égales: Assert.AreEqual (i, j); // Deux types de valeur ne représentent * pas * le même objet: Assert.AreNotSame (i, j);
Exemple 2:
string s = "A"; string t = s; // Les valeurs sont égales: Assert.AreEqual (s, t); // Les types de référence * peuvent * pointer vers le même objet: Assert.AreSame (s, t);
AreNotSame utilise l'égalité de référence (object.ReferenceEquals
) - c'est-à-dire qu'il s'agit de la même instance réelle d'un objet; AreNotEqual utilise l'égalité conceptuelle (.Equals
) - c'est-à-dire sont-ils considérés égaux.
N'est-il pas vrai qu'AreNotEqual vérifie le cas où deux objets ne sont pas égaux en termes de méthode Equals (), alors qu'AreNotSame vérifie le cas où les deux références d'objet ne sont pas les mêmes. Donc, si x et y sont deux objets égaux en termes d'Egal () mais qui ont été alloués séparément, AreNotEqual () déclencherait une assertion échouée mais pas l'autre.