2010-05-21 12 views
23

Qualcuno può dirmi perché assertSame() non riesce quando uso valori> 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! 
     } 

Sto usando JUnit 4.8.1.

+3

È necessario utilizzare 'assertSame' solo per i controlli di uguaglianza di riferimento, ad esempio' a == b'. Per l'uguaglianza, dovresti usare "assertEquals". –

risposta

44

Il motivo è l'autoboxing di Java. Si utilizza il metodo:

public static void assertSame(Object expected, Object actual) 

Funziona solo con gli oggetti. Quando si passa int s a questo metodo, Java chiama automaticamente

Integer.valueOf(int i) 

con questi valori. Pertanto, il cast a int non ha alcun effetto.

Per valori inferiori a 128 Java ha una cache, quindi assertSame() confronta l'oggetto Integer con se stesso. Per valori superiori a 127 Java crea nuove istanze, quindi assertSame() confronta un oggetto Integer con un altro. Poiché non sono la stessa istanza, il metodo assertSame() restituisce false.

si dovrebbe utilizzare il metodo:

public static void assertEquals(Object expected, Object actual) 

invece. Questo metodo utilizza il metodo equals() da Object.

+0

È corretto che JVM * deve * cache -128..127, ma per valori esterni all'intervallo, che dipende interamente dall'implementazione JVM di quale intervallo memorizza nella cache, \t _ "Ad esempio, potrebbero essere implementate meno implementazioni a memoria limitata. , salva tutti i valori char e short, nonché i valori int e long nell'intervallo da -32K a +32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5 .html # jls-5.1.7 tramite https://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127/20948389#20948389 – weston

12

assertSame accetta due argomenti Object, quindi il compilatore deve attivare automaticamente i valori letterali int in Integer.

Ciò equivale a

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

Ora, per valori compresi tra -128 e 127, la JVM memorizza nella cache i risultati di Integer.valueOf, in modo da ottenere ogni volta lo stesso Integer oggetto indietro. Per i valori al di fuori di tale intervallo, si ottengono nuovi oggetti.

Quindi per assertSame(127, 127), JUnit sta confrontando gli stessi oggetti, quindi funziona. Per assertSame(128, 128), si ottengono oggetti diversi, quindi non riesce.

Solo un altro motivo per fare attenzione con l'autoboxing.

+0

Hai ragione che la JVM deve memorizzare nella cache -128..127, ma per i valori al di fuori dell'intervallo, che dipende interamente dall'implementazione della JVM, che intervallo caches, _ "Meno implementazioni a memoria limitata potrebbero, ad esempio, memorizzare tutti i valori char e short, così come int e valori lunghi nell'intervallo tra -32K e + 32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 attraverso https://stackoverflow.com/a/20948389/360211 – weston