1 package org.hamcrest.number; 2 3 import org.hamcrest.Description; 4 import org.hamcrest.Matcher; 5 import org.hamcrest.TypeSafeMatcher; 6 7 import java.math.BigDecimal; 8 import java.math.MathContext; 9 10 public class BigDecimalCloseTo extends TypeSafeMatcher<BigDecimal> { 11 12 private final BigDecimal delta; 13 private final BigDecimal value; 14 BigDecimalCloseTo(BigDecimal value, BigDecimal error)15 public BigDecimalCloseTo(BigDecimal value, BigDecimal error) { 16 this.delta = error; 17 this.value = value; 18 } 19 20 @Override matchesSafely(BigDecimal item)21 public boolean matchesSafely(BigDecimal item) { 22 return actualDelta(item).compareTo(BigDecimal.ZERO) <= 0; 23 } 24 25 @Override describeMismatchSafely(BigDecimal item, Description mismatchDescription)26 public void describeMismatchSafely(BigDecimal item, Description mismatchDescription) { 27 mismatchDescription.appendValue(item) 28 .appendText(" differed by ") 29 .appendValue(actualDelta(item)) 30 .appendText(" more than delta ") 31 .appendValue(delta); 32 } 33 34 @Override describeTo(Description description)35 public void describeTo(Description description) { 36 description.appendText("a numeric value within ") 37 .appendValue(delta) 38 .appendText(" of ") 39 .appendValue(value); 40 } 41 actualDelta(BigDecimal item)42 private BigDecimal actualDelta(BigDecimal item) { 43 return item.subtract(value, MathContext.DECIMAL128).abs().subtract(delta, MathContext.DECIMAL128).stripTrailingZeros(); 44 } 45 46 /** 47 * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal 48 * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality 49 * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method. 50 * For example: 51 * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre> 52 * 53 * @param operand 54 * the expected value of matching BigDecimals 55 * @param error 56 * the delta (+/-) within which matches will be allowed 57 */ closeTo(BigDecimal operand, BigDecimal error)58 public static Matcher<BigDecimal> closeTo(BigDecimal operand, BigDecimal error) { 59 return new BigDecimalCloseTo(operand, error); 60 } 61 62 } 63 64