0

I have a test that sends and returns a few different values to the 'subtract' method. The first list contains the method's results. The second list contains the expected solutions. This looks a little clunky and doesn't look and/or feel very clean. Is there a way, with Hamcrest, to have the same test to be more concise? Perhaps have a smaller list declaration or having a list directly in the assertion.

@Test
public void verifySubtractWillReturnCorrectValues() {
    List<Double> results = new ArrayList<Double>(Arrays.asList(
            aCalc.subtract(14, 4), 
            aCalc.subtract(10.0, 1),
            aCalc.subtract(0b1111, 0b0011),
            aCalc.subtract(3.0F, 4.0F),
            aCalc.subtract(1L, 1L)));
    List<Double> solutions = new ArrayList<Double>() {{add(10.0); add(9.0); add(12.0); add(-1.0); add(0.0);}};
    assertThat(results, equalTo(solutions));
}
DwB
  • 37,124
  • 11
  • 56
  • 82
Nate Thompson
  • 325
  • 2
  • 12
  • 1
    A test should test one thing and one thing only. Why not make all those separate tests? – Turing85 Apr 13 '18 at 14:36
  • 2
    Possible duplicate of [JUnit - How to test a method with different values?](https://stackoverflow.com/questions/5794036/junit-how-to-test-a-method-with-different-values) – Joe Apr 13 '18 at 14:44
  • I'm not a fan of having separate tests for small assertions. If this were a more complicated test, then I would have them separated. @Turing85 – Nate Thompson Apr 13 '18 at 14:46
  • 1
    It seems like what you actually want is a parameterised test – jonrsharpe Apr 13 '18 at 14:47
  • Not quite, I'd rather only use hamcrest methods. @jonrsharpe – Nate Thompson Apr 13 '18 at 15:57
  • Why do you think that's an objection? You can use hamcrest matchers *in* a parameterised junit test. – jonrsharpe Apr 13 '18 at 15:59
  • This does not appear to be a great fit for parameterization; take a look at the `aCalc.subtract` input types. – DwB Apr 13 '18 at 16:14

2 Answers2

0

In answer to the general question: 'how can I make a concise assertion on the contents of a collection' ...

Hamcrest could be used to make the assertion much more concise, for example:

assertThat(results, Matchers.hasItems(10.0, 9.0, 12.0, -1.0, 0.0));

assertThat(results, Matchers.containsInAnyOrder(10.0, 9.0, 12.0, -1.0, 0.0));

Similarly, with AssertJ:

assertThat(results).containsExactlyInAnyOrder(10.0, 9.0, 12.0, -1.0, 0.0);

However, your test seems to be asserting outputs for several discrete inputs to your subtract() method. You could test these individually thereby removing the question of a 'assert on a collection' entirely. For example:

assertThat(aCalc.subtract(14, 4), is(10.0));
assertThat(aCalc.subtract(10.0, 1), is(9.0));
// ... etc
glytching
  • 44,936
  • 9
  • 114
  • 120
0

The problem appears to be that you are performing five actual tests in the context of one unit test method. Split them into separate tests. While significantly less compact, this technique makes clear the actual intention of each test.

Here is some example code:

@Test
public void subtractTwoInts()
{
    final Double actualResult;
    final Double expectedResult = 10.0;

    actualResult = aCalc.subtract(14, 4);

    assertEquals(
        expectedResult,
        actualResult);
}

@Test
public void subtractIntFromFloat()
{
    final Double actualResult;
    final Double expectedResult = 9.0;

    actualResult = aCalc.subtract(10.0, 1);

    assertEquals(
        expectedResult,
        actualResult);
}
DwB
  • 37,124
  • 11
  • 56
  • 82