2010-05-21 5 views
23

Может кто-нибудь сказать мне, почему assertSame() не работает, когда я использую значения> 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! 
     } 

Я использую JUnit 4.8.1.

+3

Вы должны использовать 'assertSame' только для контрольных проверок равенства - например' a == b'. Для равенства вы должны использовать 'assertEquals'. –

ответ

44

Причина - автобоксинг Java. используется метод:

public static void assertSame(Object expected, Object actual) 

Он работает только с объектами. При передаче int сек этого метода, Java автоматически вызывает

Integer.valueOf(int i) 

с этими значениями. Таким образом, приведение к int не влияет.

Для значений менее 128 Java имеет кэш, поэтому assertSame() сравнивает объект Integer с самим собой. Для значений больше 127 Java создает новые экземпляры, поэтому assertSame() сравнивает объект Integer с другим. Поскольку они не являются одним и тем же экземпляром, метод assertSame() возвращает false.

Вы должны использовать метод:

public static void assertEquals(Object expected, Object actual) 

вместо этого. Этот метод использует метод equals() от Object.

+0

Вы правы, что JVM * must * cache -128..127, но для значений вне этого диапазона, что полностью зависит от реализации JVM, к какому диапазону он кэшируется, \t _ «Менее ограниченные памятью реализации могут, например , кэшировать все значения char и short, а также значения int и long в диапазоне от -32K до + 32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5 .html # jls-5.1.7 через https://stackoverflow.com/questions/20897020/why-integer-class-caching-values-in-the-range-128-to-127/20948389#20948389 – weston

12

assertSame принимает два аргумента Object, поэтому компилятор должен автобоксации ваших int литералов в Integer.

Это эквивалентно

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

Теперь для значений между -128 и 127, JVM кэширует результаты Integer.valueOf, так что вы получите тот же Integer объект обратно каждый раз. Для значений вне этого диапазона вы возвращаете новые объекты.

Значок для assertSame(127, 127), JUnit сравнивает одни и те же объекты, следовательно, он работает. Для assertSame(128, 128) вы получаете разные объекты, поэтому он терпит неудачу.

Еще одна причина быть осторожным с автобоксированием.

+0

Вы правы что JVM должен кэшировать -128..127, но для значений вне этого диапазона, это полностью зависит от реализации JVM, к какому диапазону он кэширует: «Менее ограниченные памятью реализации могут, например, кэшировать все значения char и short, а также значения int и long в диапазоне от -32K до + 32K. "_ http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7 с помощью https://stackoverflow.com/a/20948389/360211 – weston

Смежные вопросы