Extending assertions with conditions

Assertions provided by AssertJ can be extended by using conditions, to create a condition you just have to implement org.assertj.assertions.core.Condition and its unique method matches.

Once your Condition is created, you can use it with methods : is(myCondition) or has(myCondition), both verifying that the condition is met (hint: pick the one that makes your code more readable).
Example:

// jedi is a Condition
assertThat("Yoda").is(jedi);

Conditions can be combined with :

  • not(Condition) : given condition must not be met
  • allOf(Condition...) : all given conditions must be met
  • anyOf(Condition...) : one of the given conditions must be met

You can verify that a Condition is met on elements of a collection, with the following methods:

  • are(condition) / have(condition) : all elements must meet the given condition
  • areAtLeast(n, condition) / haveAtLeast(n, condition) : at least n elements must meet the given condition
  • areAtMost(n, condition) / haveAtMost(n, condition) : no more than n elements must meet the given condition
  • areExactly(n, condition) / haveExactly(n, condition) : exactly n elements must meet the given condition

Moreover all Condition related methods have their negation counterpart, is/isNot, have/doesNotHave, are/areNot, ...

The examples below are from assertj-examples and more specifically UsingConditionExamples.java.

Let's define two similar conditions : jedi and jediPower with the same implementation just to show that code readability is better when using jedi with is and jediPower with has.

import static org.assertj.core.util.Sets.newLinkedHashSet;

static Set<String> JEDIS = newLinkedHashSet("Luke", "Yoda", "Obiwan");

// implementation with Java 8 :)
Condition<String> jediPower = new Condition<>(JEDIS::contains, "jedi power"); 

// implementation with Java 7 :(
Condition<String> jedi = new Condition<String>("jedi") {
  @Override
  public boolean matches(String value) {
    return JEDIS.contains(value);
  }
};

An small example of is(Condition) and isNot(Condition) usage including an error message.

assertThat("Yoda").is(jedi);
assertThat("Vader").isNot(jedi);
try {
  // condition not verified to show the clean error message
  assertThat("Vader").is(jedi);
} catch (AssertionError e) {
  assertThat(e).hasMessage("expecting:<'Vader'> to be:<jedi>");
}

An small example of has(Condition) and doesNotHave(Condition) usage including an error message.

assertThat("Yoda").has(jediPower);
assertThat("Solo").doesNotHave(jediPower);
try {
  // condition not verified to show the clean error message
  assertThat("Vader").has(jediPower);
} catch (AssertionError e) {
  assertThat(e).hasMessage("expecting:<'Vader'> to have:<jedi power>");
}

It is possible to verify that a certain condition is met on iterable/array elements :

// import static org.assertj.util.Sets.newLinkedHashSet;
assertThat(newLinkedHashSet("Luke", "Yoda")).are(jedi);
assertThat(newLinkedHashSet("Leia", "Solo")).areNot(jedi);

assertThat(newLinkedHashSet("Luke", "Yoda")).have(jediPower);
assertThat(newLinkedHashSet("Leia", "Solo")).doNotHave(jediPower);

assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).areAtLeast(2, jedi);
assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).haveAtLeast(2, jediPower);

assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).areAtMost(2, jedi);
assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).haveAtMost(2, jediPower);

assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).areExactly(2, jedi);
assertThat(newLinkedHashSet("Luke", "Yoda", "Leia")).haveExactly(2, jediPower);

Condition can be combined with allOf(Condition...) (logical and) or anyOf(Condition...) (logical or).

assertThat("Vader").is(anyOf(jedi, sith));
assertThat("Solo").is(allOf(not(jedi), not(sith)));

where sith condition is defined as :

static Set<String> SITHS = newHashSet("Sidious", "Vader", "Plagueis");
Condition<String> sith = new Condition<>(SITHS::contains, "sith");