11

I am running assertions like so:

assertThat(obj.getTotal()).isEqualTo(BigDecimal.valueOf(4))

I am getting

Expecting: <4.00> to be equal to: <4>

so then I tried

assertThat(obj.getTotal()).isEqualTo(BigDecimal.valueOf(4.00))

Expecting: <4.00> to be equal to: <4.0>

I found a workaround in which I would set the scale of expected value 4 to 4.00, but it seems quite irritating that I have to do so for all BigDecimal variables in my tests. Is there a better way from AssertJ that I am unaware of?

夢のの夢
  • 5,054
  • 7
  • 33
  • 63
  • 1
    The underlying issue is not with AssertJ, but that [`BigDecimal` has a weird definition of its `equal` method](https://stackoverflow.com/questions/6787142/bigdecimal-equals-versus-compareto). – Joachim Sauer Sep 03 '20 at 08:51

2 Answers2

30

You can use isEqualByComparingTo or usingComparator that use BigDecimal.compareTo which compares the actual numeric value. The equals method which is the default assertj uses does the following according to JavaDoc:

Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).

So you can do:

    assertThat(obj.getTotal())
        .usingComparator(BigDecimal::compareTo)
        .isEqualTo(BigDecimal.valueOf(4.00));

or simply:

assertThat(obj.getTotal())
    .isEqualByComparingTo(BigDecimal.valueOf(4.00));

To use with Iterable and extracting assertions:

    assertThat(asList(new Trade("1", new BigDecimal("5.200")), new Trade("2", new BigDecimal("4.00"))))
        .extracting(Trade::getId, Trade::getAmount)
        .usingComparatorForType(BigDecimal::compareTo, BigDecimal.class)
        .usingRecursiveFieldByFieldElementComparator()
        .containsExactlyInAnyOrder(tuple("1", new BigDecimal("5.2")), tuple("2", new BigDecimal("4")));
Marimuthu Madasamy
  • 13,126
  • 4
  • 30
  • 52
  • 2
    This is exactly why `isEqualByComparingTo` assertion is available. – Joel Costigliola Sep 03 '20 at 21:04
  • This fails though when comparing an iterable with extracting with tuples :( – Kango_V Jun 25 '21 at 11:27
  • @Kango_V You can use `usingComparatorForType` to assert `Iterable`s with `extracting`. I have updated the answer with an example for it. – Marimuthu Madasamy Jun 25 '21 at 23:52
  • works flawlessly! – Gaurav Feb 03 '22 at 12:18
  • 2
    Since 3.20.0 the comparison won't use any comparators set with: `usingComparatorForType(Comparator, Class)`. Equivalent would be: `usingRecursiveFieldByFieldElementComparator(RecursiveComparisonConfiguration.builder().withComparatorForType(BigDecimal::compareTo, BigDecimal.class).build())` – alsid Jul 08 '22 at 21:31
  • Note that using `new BigDecimal("1345.31")` did the trick for me instead of `new BigDecimal(1345.31)` – Pipo Aug 22 '22 at 18:05
-3

Try java.math.BigDecimal.stripTrailingZeros() method, like this:

// AssertJ
assertThat(obj.getTotal().stripTrailingZeros()).isEqualTo(BigDecimal.valueOf(4));

// Junit
assertEquals(BigDecimal.valueOf(4), obj.getTotal().stripTrailingZeros());
Peter Quan
  • 788
  • 4
  • 9