11

I have a method that do sort an array, and I want to test it, I want to compare its result with the expected one, of course that I can do it using a for loop, but i'm asking if there is a Hamcrest matcher to do the comparison

I have a class

class Person{
 String name;
 int age;
 double budget;
 Person(String name,int age,double budget){
  this.name = name;
  this.age = age;
  this.budget = budget;
 }
 @Override
 public boolean equals(Object obj) {
   if (obj == null || !(obj instanceof Person)) return false;
   Person p = (Person) obj;
   if (((Person) obj).budget == budget && ((Person) obj).age == age && ((Person) obj).name.equals(name)) {
    return true;
   }
   return false;
 }
}

and my test method is like this

@Test
public void InsertionSortOfObjectUsingComparator() {
    Person p1 = new Person("A", 18, 800);
    Person p2 = new Person("K", 15, 1800);
    Person p3 = new Person("L", 18, 600);
    Person[] persons = {p1,p2,p3};
    Person[] expected = {p3, p1, p2};
    Person[] result = (new Sort()).sort(persons, Comparator.<Person>comparingDouble(o-> o.budget);
    //want to compare the content of the two arrays result and expected; using assertThat
}

Is it possible doing it using Hamcrest ? if yes, how ?

UPDATE

yes it is possible, using IsArrayContainingInOrder.arrayContaining

    ....
    assertThat(expected, IsArrayContainingInOrder.arrayContaining((new InsertionSort().sort(persons, Comparator.comparingDouble(o -> o.budget)))));
    assertThat(3,is((new InsertionSort().sort(persons, Comparator.comparingDouble(o -> o.budget))).length));
}
octopus
  • 319
  • 1
  • 4
  • 16

3 Answers3

9

The arrays can be matched with the simplest is matcher, e.g.:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

// ...

assertThat(result, is(new byte[]{1, 2, 3}));

Under the hood it will figure out that the input is an array. It will use the appropriate matcher for arrays (i.e. not just a.equal(b)).

Pavel
  • 4,912
  • 7
  • 49
  • 69
8

There are many ways that you could do this with hamcrest. The easiest way is to use the arrayContaining matcher in Matchers class.

assertThat(result, Matchers.arrayContaining(expected));
Laksitha Ranasingha
  • 4,321
  • 1
  • 28
  • 33
  • thanks for your answer, yes I agree with you the `Matchers.arrayContaining` check that the objects in result are in the expected array, but it's negligate the ordre which i'm currently testing – octopus Jan 30 '19 at 11:53
  • The `arrayContaining` matcher fails if order is different. There's another matcher called `arrayContainingInAnyOrder`, I think that's what you are referring to. Have you tried this? – Laksitha Ranasingha Jan 30 '19 at 11:57
  • Thank you what i was looking is this `IsArrayContainingInOrder.arrayContaining` it test the order of the array too – octopus Jan 30 '19 at 12:21
  • If this solution has worked please accept the answer. Thanks. – Laksitha Ranasingha Jan 30 '19 at 12:52
  • 4
    `arrayContaining()` will not compile when `expected` is a primitive array: `byte[] result = byte[] { 0x01, 0x02, 0x03 }; byte[] exepected = byte[] { 0x01, 0x02, 0x03 }; assertThat(result, Matches.arrayContaining(expected))` will complain: `The method assertThat(T, Matcher super T>) in the type MatcherAssert is not applicable for the arguments (byte[], Matcher)` – Guss Feb 23 '20 at 16:38
0

Junit also has a built in assertArrayEquals ( https://junit.org/junit4/javadoc/4.12/org/junit/Assert.html#assertArrayEquals(java.lang.Object[],%20java.lang.Object[]) )

It recursively checks equality if your arrays contain arrays. Pretty handy, and very declarative and easy to read!

Josh
  • 4,726
  • 2
  • 20
  • 32