0

We all know how to correctly check for fractional numbers in tests (using TOLERANCE):

class OxygenTankTest {
    static final double TOLERANCE = 0.001;

    @Test
    void testFilling() {
        OxygenTank tank = OxygenTank.withCapacity(100);
        tank.fill(5.8);
        tank.fill(5.6);
        Assertions.assertEquals(0.114, tank.getStatus(), TOLERANCE);
    }
}

But my question is how to check if we need to check not the individual values - but whole objects.

For example: Need to test Summer - which performs the summation of fields

public class Summer {
    public void setSum(Item itemTo, Item itemFrom) {
        itemTo.setDiameter(itemTo.getDiameter() + itemFrom.getDiameter());
        itemTo.setLength(itemTo.getLength() + itemFrom.getLength());
    }
}

public class Item {
    private Double diameter;
    private Double length;

    public Item(Double diameter, Double length) {
        this.diameter = diameter;
        this.length = length;
    }

    public Double getDiameter() {
        return diameter;
    }

    public void setDiameter(Double diameter) {
        this.diameter = diameter;
    }

    public Double getLength() {
        return length;
    }

    public void setLength(Double length) {
        this.length = length;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Item item = (Item) o;

        if (diameter != null ? !diameter.equals(item.diameter) : item.diameter != null) return false;
        return length != null ? length.equals(item.length) : item.length == null;
    }

    @Override
    public int hashCode() {
        int result = diameter != null ? diameter.hashCode() : 0;
        result = 31 * result + (length != null ? length.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Item{");
        sb.append("diameter=").append(diameter);
        sb.append(", length=").append(length);
        sb.append('}');
        return sb.toString();
    }
}

How i try to write a test:

public class SummerTest {

    @Test
    public void setSum() {
        Summer summer = new Summer();
        Item itemFrom = new Item(2.321, 1.111);
        Item itemTo = new Item(0.999, 0.999);

        summer.setSum(itemFrom, itemTo);

        // expected
        Item expectedItem = new Item(3.32, 2.11);

        assertThat(itemFrom, equalTo(expectedItem));
    }
}

But it does not work!

java.lang.AssertionError: 
Expected: <Item{diameter=3.32, length=2.11}>
     but: was <Item{diameter=3.3200000000000003, length=2.11}>
Expected :<Item{diameter=3.32, length=2.11}>

Actual   :<Item{diameter=3.3200000000000003, length=2.11}>
 <Click to see difference>

How to properly check for compliance?

FreeOnGoo
  • 868
  • 1
  • 8
  • 26

2 Answers2

3

You overwrote the equals method that checks for exact equality. If you have objects that contain floating point values (float, double) that are considered in your equals implementation, you will want to not compare the object itself, but the values within the object:

assertEquals(expected.getDiameter(), itemFrom.getDiameter(), TOLERANCE);
assertEquals(expected.getLength(), itemFrom.getLength(), TOLERANCE);

Or if you want to get fancy you can create your own Matcher that goes into the assertThat.

hotzst
  • 7,238
  • 9
  • 41
  • 64
1

Consider changing the set up of the test to allow for exact comparisons via Item::equals:

private static final double ITEM_FROM_DIAMETER = 2.321;
private static final double ITEM_FROM_LENGTH = 1.111;
private static final double ITEM_TO_DIAMETER = 0.999;
private static final double ITEM_TO_LENGTH = 0.999;

Item itemFrom = new Item(ITEM_FROM_DIAMETER, ITEM_FROM_LENGTH);
Item itemTo = new Item(ITEM_TO_DIAMETER, ITEM_TO_LENGTH);

Item expectedItem = new Item(ITEM_FROM_DIAMETER + ITEM_TO_DIAMETER, ITEM_FROM_LENGTH + ITEM_TO_LENGTH);

Also, since Item is mutable, it would be a good idea to assert itemFrom was not changed.

Andrew S
  • 2,509
  • 1
  • 12
  • 14