Testing Floating Point JUnit 5 | Java Fresher
Fast recall
Quick revision
Core answer
BigDecimal or integer minor units when that representation matches the business rules.Interview-ready guide
Interview answer
The key thing about floating point is that doubles and floats can't represent most decimal numbers exactly, so the arithmetic accumulates tiny rounding errors. The classic example is that zero point one plus zero point two doesn't equal zero point three — it comes out as zero point three followed by a bunch of zeros and a four at the end. So if I write a plain assertEquals expecting zero point three, the test fails, even though the math is conceptually correct.
The fix in JUnit is to use the delta overload of assertEquals, where I pass a third argument that's a small tolerance, like zero point oh oh oh one. That says the values just have to be within that tolerance of each other. AssertJ has the same idea with isCloseTo and within. The thing to be careful about is picking a sensible tolerance — too loose and you start hiding real bugs.
For anything involving money, though, I wouldn't use doubles at all. I'd use BigDecimal, which does exact decimal arithmetic, so there's no drift. The one gotcha there is that BigDecimal's equals method also compares the scale, so zero point three zero is not equal to zero point three by equals. When I'm comparing values, I use compareTo and check it returns zero, which ignores the scale difference.
Common mistakes are comparing doubles without a delta, using an overly large delta, and using doubles for currency.
Testing Floating Point JUnit 5 | Java Fresher
Direct Answer
For an approximate floating-point result, use assertEquals(expected, actual, delta) or AssertJ's isCloseTo with a tolerance chosen from the domain. Do not copy one epsilon into every test. For exact decimal quantities such as accounting values, use BigDecimal or integer minor units when that representation matches the business rules.
Deep Dive & Architecture
A double stores values in binary, so many ordinary decimal fractions cannot be represented exactly. The calculated result may be extremely close to the expected value without being bit-for-bit equal. JUnit therefore provides assertEquals(expected, actual, delta), where the assertion passes when the difference is within the chosen tolerance.
For example, assertEquals(0.3, 0.1 + 0.2, 1e-9) allows the tiny representation error but still catches a meaningful calculation error. The delta must come from the precision the application actually needs; an oversized value can hide a bug. Currency is a different case: use BigDecimal for exact decimal rules. Remember that BigDecimal.equals also compares scale, while compareTo(...) == 0 compares numerical value.
Common Mistakes & Pitfalls
- Exact comparison for approximate output. Use a tolerance when the algorithm permits rounding error.
- Arbitrary epsilon. Too loose hides bugs; too tight makes tests brittle. Derive it from the requirement.
- Binary floating point for exact decimal accounting. Choose a decimal or minor-unit model that matches the money rules.
BigDecimal.equalswhen scale is irrelevant.equalsdistinguishes0.30and0.3; usecompareTowhen the contract is numerical equality.
Check your understanding
Answer these without looking back at the article.
- What is the Arrange-Act-Assert (AAA) pattern in unit testing?
- How do you use assertThrows to test exception scenarios in JUnit 5?
- How do you verify that a list returned by a method has the correct content in JUnit 5?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.