2010-05-21 6 views
23

Quelqu'un peut-il me dire pourquoi assertSame() échoue lorsque j'utilise des valeurs> 127?JUnit - assertSame

 import static org.junit.Assert.*; 

     ... 

     @Test 
     public void StationTest1() { 
      .. 

      assertSame(4, 4);   // OK 
      assertSame(10, 10);  // OK 
      assertSame(100, 100);  // OK 
      assertSame(127, 127);  // OK 
      assertSame(128, 128);   // raises an junit.framework.AssertionFailedError! 
      assertSame(((int) 128),((int) 128)); // also junit.framework.AssertionFailedError! 
     } 

J'utilise JUnit 4.8.1.

+3

Vous devez utiliser 'assertSame' uniquement pour les vérifications d'égalité de référence - par exemple' a == b'. Pour l'égalité, vous devez utiliser 'assertEquals'. –

Répondre

44

La raison en est l'autoboxing de Java. Vous utilisez la méthode:

public static void assertSame(Object expected, Object actual) 

Il fonctionne uniquement avec des objets. Lorsque vous passez int s à cette méthode, Java appelle automatiquement

Integer.valueOf(int i) 

avec ces valeurs. Donc, la distribution à int n'a aucun effet.

Pour les valeurs inférieures à 128 Java a un cache, donc assertSame() compare l'objet Integer avec lui-même. Pour les valeurs supérieures à 127, Java crée de nouvelles instances, donc assertSame() compare un objet Integer avec un autre. Parce qu'ils ne sont pas la même instance, la méthode assertSame() renvoie false.

Vous devez utiliser la méthode:

public static void assertEquals(Object expected, Object actual) 

à la place. Cette méthode utilise la méthode equals() de Object.

+0

Vous avez raison que la JVM * doit * mettre en cache -128..127, mais pour les valeurs en dehors de cette plage, cela dépend entièrement de l'implémentation de la JVM. \t _ "Moins d'implémentations limitées en mémoire peuvent, par exemple , cache toutes les valeurs char et short, ainsi que les valeurs int et long dans la plage de -32K à +32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5 .html # jls-5.1.7 via https://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127/20948389#20948389 – weston

12

assertSame prend deux arguments Object, et donc le compilateur doit autoboxer vos littéraux int en Integer.

Cela équivaut à

assertSame(Integer.valueOf(128), Integer.valueOf(128)); 

Maintenant, pour des valeurs comprises entre -128 et 127, la machine virtuelle Java en cache les résultats de Integer.valueOf, de sorte que vous obtenez le même objet Integer retour à chaque fois. Pour les valeurs en dehors de cette plage, vous récupérez de nouveaux objets.

Donc pour assertSame(127, 127), JUnit compare les mêmes objets, donc cela fonctionne. Pour assertSame(128, 128), vous obtenez différents objets, donc cela échoue.

Juste une autre raison de faire attention à l'autoboxing.

+0

Vous avez raison que la JVM doit mettre en cache -128..127, mais pour les valeurs en dehors de cette plage, cela dépend entièrement de l'implémentation JVM dans quelle plage elle met en cache, _ "Moins d'implémentations limitées en mémoire peuvent, par exemple, mettre en cache toutes les valeurs char et short ainsi que les valeurs int et longues dans la plage de -32K à +32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 via https://stackoverflow.com/a/20948389/360211 – weston