Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

An Intro to AssertJ and Collections

DZone's Guide to

An Intro to AssertJ and Collections

When working with collections, AssertJ and its various methods make it easy to pull up what you need based on your specified criteria.

· Java Zone
Free Resource

Try Okta to add social login, MFA, and OpenID Connect support to your Java app in minutes. Create a free developer account today and never build auth again.

When programming in Java, you often end up writing methods returning a collection of objects. They certainly have their place in your application, but testing them can be a little tricky. Depending on the implementation of the underlying collection, the order of the elements may be different, the equals on collections is not always obvious, and so on. I have come across multiple examples of such cases in my career, and I decided to pick a couple of them and show a way to tackle them with AssertJ, the assertions library you should definitely be using.

All the recipes follow the same format. I present a short description, followed by the implementation of the test. The test is always successful, to avoid confusion. Each recipe ends with a short remark, like what other situations can this be used for. I’m also using the Guava library to create the collections, as vanilla Java doesn’t really provide a way to do that.

We could use some Java primitives like String or int for the sake of the tests, but in the wild, this is not seen very often. Let’s say we’re making an RPG game, so we’re going to have a lot of POJOs, representing different characters and objects in the game. For example, a class representing a monster:

public class Monster {
    private String id;
    private String name;

    // constructor for all arguments
    // getters and setters
    // equals based on id and hashCode
}


The code for both the model and the tests is available as a gist.

Collection Contains an Expected Element

Let’s kick off with the simplest one. You want to be sure that the list returning from one method contains an element (or elements) that is interesting to you. AssertJ allows you to achieve that with the contains method and its negative counterpart doesNotContain. The method checks whether the given elements are in the collection:

assertThat(beasts).contains(direwolf);
assertThat(beasts).contains(werewolf);

// the same
assertThat(beasts).contains(werewolf, direwolf);

assertThat(beasts).doesNotContain(vampire);


The first two lines check that direwolf and werewolf belong to the beasts collection. As you can see in the next line, you can also verify multiple elements.

One thing to remember is that the method cares neither about all the elements (i.e. it doesn’t check whether there are other elements too) nor about the order.

Collection Contains All the Elements I Am Interested in, No Matter the Order

When generating collections, it’s pretty often that you don’t care about the order of the elements. This is where containsExactlyInAnyOrder is useful:

assertThat(beasts).containsExactlyInAnyOrder(direwolf, werewolf);
assertThat(beasts).containsExactlyInAnyOrder(werewolf, direwolf);


This assumes that the count of the elements is exactly the same, but the order doesn’t play any role. You can achieve a similar goal using containsExactlyElementsOf, which takes an Iterable, but it’s not as elegant.

Collection Contains All the Elements I Am Interested in, in a Given Order

This is similar to the previous one, but without ...InAnyOrder (duh!):

assertThat(beasts).containsExactly(direwolf, werewolf);

// this one is false this time
// assertThat(beasts).containsExactly(werewolf, direwolf);


Collection Contains Only the Given Elements

This sounds similar to the first one, but there’s a little twist: We don’t care about the counts, we only care if there are other elements:

List<Monster> group = Lists.newArrayList(direwolf, direwolf, werewolf, werewolf, werewolf);

assertThat(group).containsOnly(direwolf, werewolf);
assertThat(group).containsOnly(werewolf, direwolf);


This can be useful, for example, for a collection of enumerations that potentially can be repeated multiple times. Remember, this doesn’t check any order!

Collection With Elements Appearing Only Once

This sounds similar to the previous one. Even the method is named similarly: containsOnlyOnce. The idea behind it is very different, though. While containsOnly checks whether there are no other elements in the collection, this one checks that the given element exists in the collection (just like contains), and it appears exactly once:

List<Monster> group = Lists.newArrayList(direwolf, direwolf, werewolf, vampire);

assertThat(group).containsOnlyOnce(vampire);
assertThat(group).containsOnlyOnce(werewolf);

// this one is false
// assertThat(group).containsOnlyOnce(direwolf);


It sounds like a good idea to have a method that allows you to verify more complex counts, but unfortunately, at the moment of writing this post, there is no such method.

Collection of Elements With Given Properties

Now, here's something cool (it’s cool because I wrote that). When you want to check that the collection contains the elements that have a given property set to an expected value, you can use the extracting method. With Java 8 lambda functions, it greatly increases readability:

assertThat(beasts).extracting(Monster::getName)
                  .containsExactly("Direwolf", "Werewolf");


A supplemental method is flatExtracting. It is used for properties that return List, and actually merges the lists from the properties.

The recipes described above are the most common use cases for writing tests of methods that return collections. If you feel that I am missing something, please let me know!

Build and launch faster with Okta’s user management API. Register today for the free forever developer edition!

Topics:
java ,assertj ,assertions ,tdd ,tutorial

Published at DZone with permission of Mateusz Haligowski. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}