web-dev-qa-db-fra.com

La méthode assertEquals de Java est-elle fiable?

Je sais que == a quelques problèmes lorsque l'on compare deux Strings. Il semble que String.equals() soit une meilleure approche. Eh bien, je fais des tests avec JUnit et j’ai tendance à utiliser assertEquals(str1, str2). Est-ce un moyen fiable d'affirmer que deux chaînes contiennent le même contenu? J'utiliserais assertTrue(str1.equals(str2)), mais vous n'aurez alors pas l'avantage de voir quelles sont les valeurs attendues et réelles en cas d'échec.

Sur une note connexe, quelqu'un at-il un lien vers une page ou un fil de discussion expliquant clairement les problèmes rencontrés avec str1 == str2?

192
DivideByHero

Vous devriez toujours utiliser .equals() lorsque vous comparez Strings en Java.

JUnit appelle la méthode .equals() pour déterminer l'égalité dans la méthode assertEquals(Object o1, Object o2).

Vous êtes donc en sécurité avec assertEquals(string1, string2). (Parce que Strings sont Objects)

Voici un lien vers une grande question de Stackoverflow concernant certaines des différences entre == et .equals().

265
jjnguy

assertEquals utilise la méthode equals à des fins de comparaison. Il existe une assertion différente, assertSame, qui utilise l'opérateur ==.

Pour comprendre pourquoi == ne devrait pas être utilisé avec des chaînes, vous devez comprendre ce que fait ==: il effectue un contrôle d'identité. C'est-à-dire que a == b vérifie si a et b se rapportent à même objet. Il est intégré au langage et son comportement ne peut pas être modifié par différentes classes. La méthode equals, en revanche, peut être remplacée par des classes. Bien que son comportement par défaut (dans la classe Object) consiste à effectuer une vérification d’identité à l’aide de l’opérateur ==, de nombreuses classes, y compris String, la remplacent pour effectuer une vérification "d’équivalence". Dans le cas de String, au lieu de vérifier si a et b se rapportent au même objet, a.equals(b) vérifie si les objets auxquels ils font référence sont des chaînes contenant exactement les mêmes personnages.

Temps d’analogie: imaginez que chaque objet String soit un morceau de papier avec quelque chose d’écrit. Disons que j'ai deux feuilles de papier sur lesquelles est écrit "Foo" et une autre sur laquelle est écrit "Bar". Si je prends les deux premiers morceaux de papier et que j'utilise == pour les comparer, cela retournera false car il est essentiellement question de "S'agit-il du même morceau de papier?". Il n'est même pas nécessaire de regarder ce qui est écrit sur le papier. Le fait que je lui donne deux bouts de papier (plutôt que le même deux fois) signifie qu'il retournera false. Si j'utilise equals, cependant, la méthode equals lira les deux bouts de papier et veillera à ce qu'ils disent la même chose ("Foo"), et ainsi ils retourneront true .

Le problème avec les chaînes est que le Java a le concept "d'interner" des chaînes, ce qui est (automatiquement) automatiquement effectué sur les littéraux de chaîne de votre code. Cela signifie que si vous avez deux littéraux de chaîne équivalents dans votre code (même s'ils appartiennent à des classes différentes), ils feront tous deux référence au même objet String. Cela fait que l'opérateur == renvoie true plus souvent que l'on pourrait s'y attendre.

30
Laurence Gonsalves

En un mot, vous pouvez avoir deux objets String contenant les mêmes caractères, mais différents objets (dans des emplacements de mémoire différents). L'opérateur == vérifie que deux références pointent sur le même objet (emplacement mémoire), mais la méthode equals () vérifie si les caractères sont identiques.

Généralement, vous souhaitez vérifier si deux chaînes contiennent les mêmes caractères, et non si elles pointent vers le même emplacement de mémoire.

7
Ken Liu

Oui, il est utilisé tout le temps pour les tests. Il est très probable que la structure de test utilise .equals () pour de telles comparaisons.

Ci-dessous un lien expliquant "l'erreur d'égalité de chaîne". Pour l'essentiel, les chaînes dans Java sont des objets, et lorsque vous comparez l'égalité d'objet, elles sont généralement comparées en fonction de l'adresse de la mémoire et non du contenu. De ce fait, deux chaînes n'occuperont pas la même adresse, même si leur contenu est identique, de sorte qu'elles ne correspondent pas correctement, même si elles se ressemblent une fois imprimées.

http://blog.enrii.com/2006/03/15/Java-string-equality-common-mistake/

3
Soviut
public class StringEqualityTest extends TestCase {
    public void testEquality() throws Exception {
        String a = "abcde";
        String b = new String(a);
        assertTrue(a.equals(b));
        assertFalse(a == b);
        assertEquals(a, b);
    }
}
3
Carl Manaster

Le JUnit assertEquals(obj1, obj2) appelle effectivement obj1.equals(obj2).

Il y a aussi assertSame(obj1, obj2) qui fait obj1 == obj2 (c’est-à-dire qu'il vérifie que obj1 et obj2 font référence à l’instance identique). en essayant d'éviter.

Donc ça va.

3
Jack Leow

"L'opérateur == vérifie si deux Objects sont exactement les mêmes Object."

http://leepoint.net/notes-Java/data/strings/12stringcomparison.html

String est un Object en Java, il entre donc dans cette catégorie de règles de comparaison.

0
Zachery Delafosse