JUnit Assert with BigDecimal

57,130

Solution 1

assertSame tests that the two objects are the same objects, i.e. that they are ==:

Asserts that two objects refer to the same object. If they are not the same, an AssertionError without a message is thrown.

In your case, since bd1 and bd2 are both new BigDecimal, the objects aren't the same, hence the exception.

What you want is to use assertEquals, that tests if two objects are equal, i.e. .equals:

Asserts that two objects are equal. If they are not, an AssertionError without a message is thrown. If expected and actual are null, they are considered equal.

BigDecimal bd1 = new BigDecimal (1000);
BigDecimal bd2 = new BigDecimal (1000);
org.junit.Assert.assertEquals(bd1,bd2);

Solution 2

The official junit solution to assert that two BigDecimal are matematically equal is to use hamcrest.

With java-hamcrest 2.0.0.0 we can use this syntax:

    // import static org.hamcrest.MatcherAssert.assertThat;
    // import org.hamcrest.Matchers;

    BigDecimal a = new BigDecimal("100")
    BigDecimal b = new BigDecimal("100.00")
    assertThat(a,  Matchers.comparesEqualTo(b));

Hamcrest 1.3 Quick Reference

Solution 3

assertSamechecks if both objects are the same instance. assertEqualschecks if the numbers are equal in value and scale, that means i.e. 1000 is not equal to 1000.00. If you want to compare only the numeric value, you should use compareTo() method from BigDecimal.

For example:

BigDecimal bd1 = new BigDecimal (1000.00);
BigDecimal bd2 = new BigDecimal (1000);
org.junit.Assert.assertTrue(bd1.compareTo(bd2) == 0); 

Solution 4

Comparing BigDecimal with compareTo() works (as in: it ignore the scale and compare the actual number) but when unit testing it's useful to know what's the actual number, specially when the test fail.

An option I've used in this case is stripTrailingZeros() on both BigDecimal:

assertEquals(new BigDecimal("150").stripTrailingZeros(),
                    otherBigDecimal.stripTrailingZeros());

What this function does is remove zeroes without changing the number, so "150" is converted in "1.5E+2": this way it doesn't matter if you have 150, 150.00 or other form in otherBigDecimal because they get normalized into the same form.

The only difference is a null in otherBigDecimal would give a NullPointerException instead of an assertion error.

Solution 5

The method assertSame tests that both are the same object. However, you have two objects which have the same value. To test this, you can use assertEquals.

However, you should be aware of some unexpected behavior when using assertEquals (which depends on the equals method) on BigDecimals. For example, new BigDecimal("100").divide(new BigDecimal("10.0")).equals(new BigDecimal("10")) evaluates to false because equals also looks at the scale of the BigDecimal instances.

In many circumstances it is better to compare BigDecimals by using the compareTo method:

assertTrue(bd1.compareTo(bd2) == 0);
Share:
57,130
kAnGeL
Author by

kAnGeL

Updated on February 26, 2021

Comments

  • kAnGeL
    kAnGeL over 3 years

    I want to use assert between 2 two decimal, I use this:

    BigDecimal bd1 = new BigDecimal (1000);
    BigDecimal bd2 = new BigDecimal (1000);
    org.junit.Assert.assertSame (bd1,bd2);
    

    but the JUnit log shows:

    expected <1000> was not: <1000>