2010-05-21 24 views
23

¿Puede alguien decirme por qué assertSame() falla cuando uso valores> 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! 
     } 

Estoy usando JUnit 4.8.1.

+3

Debe usar 'assertSame' solo para verificaciones de referencia de igualdad, por ejemplo' a == b'. Para la igualdad, debe usar 'assertEquals'. –

Respuesta

44

El motivo es el autoboxing de Java. Se utiliza el método:

public static void assertSame(Object expected, Object actual) 

Sólo funciona con objetos. Cuando se pasa int s a este método, Java llama automáticamente

Integer.valueOf(int i) 

con estos valores. Entonces el lanzamiento a int no tiene efecto.

Para valores inferiores a 128 Java tiene un caché, por lo que assertSame() compara el objeto Integer consigo mismo. Para valores superiores a 127 Java crea nuevas instancias, por lo que assertSame() compara un objeto Integer con otro. Como no son la misma instancia, el método assertSame() devuelve falso.

se debe utilizar el método:

public static void assertEquals(Object expected, Object actual) 

lugar. Este método usa el método equals() del Object.

+0

Tiene la razón de que JVM * debe * caché -128..127, pero para valores fuera de ese rango, eso depende completamente de la implementación de JVM qué rango almacena en caché, \t _ "Menos implementaciones de memoria limitada, por ejemplo , guarde todos los valores char y cortos, así como los valores int y long en el rango de -32K a +32 K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5 .html # jls-5.1.7 a través de https://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127/20948389#20948389 – weston

12

assertSame toma dos argumentos Object, por lo que el compilador tiene que autobox sus literales int en Integer.

Esto es equivalente a

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

Ahora para valores entre -128 y 127, la JVM se almacena en caché los resultados de Integer.valueOf, para que tenga la misma Integer objeto de nuevo cada vez. Para valores fuera de ese rango, recuperas objetos nuevos.

Así que para assertSame(127, 127), JUnit está comparando los mismos objetos, por lo tanto funciona. Para assertSame(128, 128), obtienes diferentes objetos, por lo que falla.

Simplemente otra razón para tener cuidado con el autoboxing.

+0

Tiene razón que la JVM debe almacenar en caché -128..127, pero para valores fuera de ese rango, depende totalmente de la implementación de JVM qué rango almacena en caché, _ "Menos implementaciones con memoria limitada podrían, por ejemplo, almacenar en caché todos los caracteres y valores cortos, así como los valores int y long en el rango de -32K a +32 K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 via https://stackoverflow.com/a/20948389/360211 – weston