Inside JavaBlackBelt

The JavaBlackBelt team blog.

Wednesday, May 7, 2008

JUnit and auto-boxing

posted by Moandji Ezana
After that gigantic previous post, I thought it'd be good to post something simpler and more widely applicable.

I came across a little JUnit assertion gotcha that had me puzzled for a second. I was testing this (note, calculateDurationInSeconds() returns a long)
assertEquals(120, subjectUnderTest.calculateDurationInSeconds());
and getting the following, less-than-helpful test failure message
expected: <120> but was: <120>
I figured this one out pretty quickly because my Eclipse underlines cases of auto-boxing/unboxing. Since the assertEquals(Object, Object) method is being used, my int is becoming an Integer and the long returned by the method is becoming a Long. Obviously, any equals() comparaison is going to fail. I corrected this by using the long literal notation:
assertEquals(120L, subjectUnderTest.calculateDurationInSeconds());
What with all the conversion already going on between the presentation and data layers, I'm trying to generalise the practice of making primitive/wrapper conversions explicit, just in case.

Labels: ,

4 Comments:

  • At May 9, 2008 10:47 AM , Blogger Chinh said...

    That's a weird bug you got there. I tried reproducing it but the test succeeded here:

    import static org.junit.Assert.assertEquals;

    import org.junit.Test;

    public class Hello {

    public long calculateDurationInSeconds() {
    return 120;
    }

    @Test
    public void test() {
    assertEquals(120, calculateDurationInSeconds());
    }

    }

     
  • At May 9, 2008 11:04 AM , Blogger Moandji Ezana said...

    Really? I just ran your code and the test failed... :)

    I'm not sure where the difference could be coming from. I'm using JUnit 4.4, Java 1.6.0.03 and Eclipse 3.3.1.1 on Ubuntu Gutsy Gibbon.

    Still, I don't see how it could work for you, purely on a Java level:

    new Long(1).equals(new Integer(1)) == false

    and here's the method that's called in the JUnit Assert class:

    private static boolean isEquals(Object expected, Object actual) {
      return expected.equals(actual);
    }

     
  • At May 27, 2008 3:34 AM , Blogger Chinh said...

    I had a deeper look at how things were going on and found the reason:

    - The value 120 was boxed into an Integer value, as we all guessed.

    - After a few method call, the real comparison code was like below:

    private static boolean isEquals(Object expected, Object actual) {
    if (expected instanceof Number && actual instanceof Number)
    return ((Number) expected).longValue() == ((Number) actual).longValue();
    return expected.equals(actual);
    }

    (Assert class line 102)

    So in my case the primitive long values were compared, that's why the test passed.

    Maybe you should try it on your side and see how things go.

     
  • At May 27, 2008 3:43 AM , Blogger Chinh said...

    OK my JUnit version was 4.3.1, a bit outdated.

    But really I think that really was a very big change that spoiled everything.

     

Post a Comment

Links to this post:

Create a Link

<< Home