Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assert equals between 2 Lists in Junit

How can I make an equality assertion between lists in a JUnit test case? Equality should be between the content of the list.

For example:

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
List<String> numbers3 = Arrays.asList("one", "two", "four"); 

// numbers should be equal to numbers2
//numbers should not be equal to numbers3
like image 995
Kamal Avatar asked Jul 13 '10 11:07

Kamal


People also ask

How do you assert two lists in JUnit?

Using JUnit We can use the logic below to compare the equality of two lists using the assertTrue and assertFalse methods. In this first test, the size of both lists is compared before we check if the elements in both lists are the same. As both of these conditions return true, our test will pass.

How do you assert two lists are equal?

equals() method. A simple solution to compare two lists of primitive types for equality is using the List. equals() method. It returns true if both lists have the same size, and all corresponding pairs of elements in both lists are equal.

How do you assert two ArrayLists?

Is there a way to test for the equality of two arrayLists of whatever type in Junit? You can check the equality of two ArrayLists (really, any two List objects) using equals , so you should be able to use JUnit's assertEquals method and it will work just fine.


11 Answers

For junit4! This question deserves a new answer written for junit5.

I realise this answer is written a couple years after the question, probably this feature wasn't around then. But now, it's easy to just do this:

@Test
public void test_array_pass()
{
  List<String> actual = Arrays.asList("fee", "fi", "foe");
  List<String> expected = Arrays.asList("fee", "fi", "foe");

  assertThat(actual, is(expected));
  assertThat(actual, is(not(expected)));
}

If you have a recent version of Junit installed with hamcrest, just add these imports:

import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;

http://junit.org/junit4/javadoc/latest/org/junit/Assert.html#assertThat(T, org.hamcrest.Matcher)

http://junit.org/junit4/javadoc/latest/org/hamcrest/CoreMatchers.html

http://junit.org/junit4/javadoc/latest/org/hamcrest/core/Is.html

like image 168
djeikyb Avatar answered Nov 03 '22 01:11

djeikyb


For JUnit 5

you can use assertIterableEquals :

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");

Assertions.assertIterableEquals(numbers, numbers2);

or assertArrayEquals and converting lists to arrays :

List<String> numbers = Arrays.asList("one", "two", "three");
List<String> numbers2 = Arrays.asList("one", "two", "three");
Assertions.assertArrayEquals(numbers.toArray(), numbers2.toArray());
like image 41
Michał Krzywański Avatar answered Nov 03 '22 00:11

Michał Krzywański


Don't transform to string and compare. This is not good for perfomance. In the junit, inside Corematchers, there's a matcher for this => hasItems

List<Integer> yourList = Arrays.asList(1,2,3,4)    
assertThat(yourList, CoreMatchers.hasItems(1,2,3,4,5));

This is the better way that I know of to check elements in a list.

like image 35
Andre Fonseca Avatar answered Nov 03 '22 00:11

Andre Fonseca


assertEquals(Object, Object) from JUnit4/JUnit 5 or assertThat(actual, is(expected)); from Hamcrest proposed in the other answers will work only as both equals() and toString() are overrided for the classes (and deeply) of the compared objects.

It matters because the equality test in the assertion relies on equals() and the test failure message relies on toString() of the compared objects.
For built-in classes such as String, Integer and so for ... no problem as these override both equals() and toString(). So it is perfectly valid to assert List<String> or List<Integer> with assertEquals(Object,Object).
And about this matter : you have to override equals() in a class because it makes sense in terms of object equality, not only to make assertions easier in a test with JUnit.
To make assertions easier you have other ways.
As a good practice I favor assertion/matcher libraries.

Here is a AssertJ solution.

org.assertj.core.api.ListAssert.containsExactly() is what you need : it verifies that the actual group contains exactly the given values and nothing else, in order as stated in the javadoc.

Suppose a Foo class where you add elements and where you can get that.
A unit test of Foo that asserts that the two lists have the same content could look like :

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception { 
   Foo foo = new Foo();
   foo.add("One", "Two", "Three");
   Assertions.assertThat(foo.getElements())
             .containsExactly("One", "Two", "Three");
}

A AssertJ good point is that declaring a List as expected is needless : it makes the assertion straighter and the code more readable :

Assertions.assertThat(foo.getElements())
         .containsExactly("One", "Two", "Three");

But Assertion/matcher libraries are a must because these will really further.
Suppose now that Foo doesn't store Strings but Bars instances.
That is a very common need. With AssertJ the assertion is still simple to write. Better you can assert that the list content are equal even if the class of the elements doesn't override equals()/hashCode() while JUnit way requires that :

import org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple.tuple;
import org.junit.jupiter.api.Test;

@Test
void add() throws Exception {
    Foo foo = new Foo();
    foo.add(new Bar(1, "One"), new Bar(2, "Two"), new Bar(3, "Three"));
    Assertions.assertThat(foo.getElements())
              .extracting(Bar::getId, Bar::getName)
              .containsExactly(tuple(1, "One"),
                               tuple(2, "Two"),
                               tuple(3, "Three"));
}
like image 36
davidxxx Avatar answered Nov 03 '22 01:11

davidxxx


This is a legacy answer, suitable for JUnit 4.3 and below. The modern version of JUnit includes a built-in readable failure messages in the assertThat method. Prefer other answers on this question, if possible.

List<E> a = resultFromTest();
List<E> expected = Arrays.asList(new E(), new E(), ...);
assertTrue("Expected 'a' and 'expected' to be equal."+
            "\n  'a'        = "+a+
            "\n  'expected' = "+expected, 
            expected.equals(a));

For the record, as @Paul mentioned in his comment to this answer, two Lists are equal:

if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface.

See the JavaDocs of the List interface.

like image 40
Bart Kiers Avatar answered Nov 03 '22 02:11

Bart Kiers


If you don't care about the order of the elements, I recommend ListAssert.assertEquals in junit-addons.

Link: http://junit-addons.sourceforge.net/

For lazy Maven users:

    <dependency>
        <groupId>junit-addons</groupId>
        <artifactId>junit-addons</artifactId>
        <version>1.4</version>
        <scope>test</scope>
    </dependency>
like image 30
Viktor Nordling Avatar answered Nov 03 '22 02:11

Viktor Nordling


You can use assertEquals in junit.

import org.junit.Assert;   
import org.junit.Test;

    @Test
    public void test_array_pass()
    {
        List<String> actual = Arrays.asList("fee", "fi", "foe");
        List<String> expected = Arrays.asList("fee", "fi", "foe");
        Assert.assertEquals(actual,expected);
    }

If the order of elements is different then it will return error.

If you are asserting a model object list then you should override the equals method in the specific model.

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (obj != null && obj instanceof ModelName) {
            ModelName other = (ModelName) obj;
            return this.getItem().equals(other.getItem()) ;
        }
        return false;
    }
like image 26
Dhyan Mohandas Avatar answered Nov 03 '22 01:11

Dhyan Mohandas


if you don't want to build up an array list , you can try this also

@Test
public void test_array_pass()
{
  List<String> list = Arrays.asList("fee", "fi", "foe");
  Strint listToString = list.toString();
  Assert.assertTrue(listToString.contains("[fee, fi, foe]"));   // passes  
}
like image 32
Arun Pratap Singh Avatar answered Nov 03 '22 02:11

Arun Pratap Singh


List<Integer> figureTypes = new ArrayList<Integer>(
                           Arrays.asList(
                                 1,
                                 2
                            ));

List<Integer> figureTypes2 = new ArrayList<Integer>(
                           Arrays.asList(
                                 1,
                                 2));

assertTrue(figureTypes .equals(figureTypes2 ));
like image 40
Ruslan Gafiullin Avatar answered Nov 03 '22 02:11

Ruslan Gafiullin


I know there are already many options to solve this issue, but I would rather do the following to assert two lists in any oder:

assertTrue(result.containsAll(expected) && expected.containsAll(result))
like image 26
Kh.Taheri Avatar answered Nov 03 '22 01:11

Kh.Taheri


You mentioned that you're interested in the equality of the contents of the list (and didn't mention order). So containsExactlyInAnyOrder from AssertJ is a good fit. It comes packaged with spring-boot-starter-test, for example.

From the AssertJ docs ListAssert#containsExactlyInAnyOrder:

Verifies that the actual group contains exactly the given values and nothing else, in any order. Example:

 // an Iterable is used in the example but it would also work with an array
 Iterable<Ring> elvesRings = newArrayList(vilya, nenya, narya, vilya);

 // assertion will pass
 assertThat(elvesRings).containsExactlyInAnyOrder(vilya, vilya, nenya, narya);

 // assertion will fail as vilya is contained twice in elvesRings.
 assertThat(elvesRings).containsExactlyInAnyOrder(nenya, vilya, narya);
like image 39
David Good Avatar answered Nov 03 '22 01:11

David Good