AssertJ Core latest news

Release date : 2017-01-21

  • Fix extracting properties from default getter method.

Release date : 2016-11-27

  • Fix filteredOn(Predicate) that was only working with List.

Release date : 2016-11-21

This release includes all changes from AssertJ core 2.6.0 and adds the following that are Java 8 specific.

Thanks to Pascal Schumacher, Mike Kobit, Clément Mathieu, Kseniya Panasyuk, Gaël Lhez, Valeriy Vyrva and Filip Hrisafov for their contributions.

  • Parameterize registerFormatterForType with type. (Kseniya Panasyuk)
  • Predicate assertions error message improvements. (Filip Hrisafov)
  • Allow to pass a Predicate description to allMatch iterable/array assertion. (Filip Hrisafov)
  • Varargs warning removal. (Gaël Lhez)
  • Add missing assertThat in WithAssertions. (Clément Mathieu)
  • A bunch of code cleanup and javadoc improvements. (Pascal Schumacher, Mike Kobit)
  • Fix stack overflow for completable future toStringOf joining on another future that cycles back to the first. (Kseniya Panasyuk)

Verifies that the actual value is an instance of the given type satisfying the given requirements expressed as a Consumer.

This is typically used when one knows the real type of the object under test and wants to perform strongly typed assertions without having to do an explicit cast.

Example :

// Build Jedi but declare them as Object (second parameter is the light saber color)
Object yoda = new Jedi("Yoda", "Green");
Object luke = new Jedi("Luke Skywalker", "Green");

Consumer<Jedi> jediRequirements = jedi -> {
   assertThat(jedi.getLightSaberColor()).isEqualTo("Green");
   assertThat(jedi.getName()).doesNotContain("Dark");
};

// assertions succeed:
assertThat(yoda).isInstanceOfSatisfying(Jedi.class, jediRequirements);
assertThat(luke).isInstanceOfSatisfying(Jedi.class, jediRequirements);

Verifies that all elements satisfy the given requirements expressed as a Consumer. This is typically used to perform a group of assertions on every element of the iterable/array under test.

Example :

assertThat(myIcelanderFriends).allSatisfy(person -> {
                                 assertThat(person.getCountry()).isEqualTo("Iceland");
                                 assertThat(person.getPhoneCountryCode()).isEqualTo("+354");
                              });

Call map/flatMap on the Optional under test, assertions chained afterwards are performed on the Optional resulting from the map/flatMap call.

Example :

// map example
assertThat(Optional.of("42")).contains("42")
                             .map(String::length)
                             .contains(2);

// flatMap examples
Function<String, Optional<String>> UPPER_CASE_OPTIONAL_STRING
          = s -> s == null ? Optional.empty() : Optional.of(s.toUpperCase());

assertThat(Optional.of("something")).contains("something")
                                    .flatMap(UPPER_CASE_OPTIONAL_STRING)
                                    .contains("SOMETHING");

assertThat(Optional.<String> empty()).flatMap(UPPER_CASE_OPTIONAL_STRING)
                                     .isEmpty();

assertThat(Optional.<String> ofNullable(null)).flatMap(UPPER_CASE_OPTIONAL_STRING)
                                              .isEmpty();

Verifies that the actual Map contains the given key and that its value satisfies the given requirements expressed as a Consumer.

Example:

Map<Ring, TolkienCharacter> ringBearers = new HashMap<>();
ringBearers.put(nenya, galadriel);
ringBearers.put(narya, gandalf);
ringBearers.put(vilya, elrond);
ringBearers.put(oneRing, frodo);

// this assertion will pass
assertThat(ringBearers).hasEntrySatisfying(nenya, character -> {
   assertThat(character.getName()).contains("driel");
   assertThat(character.getRace()).isEqualTo(ELF);
});

// this assertion will fail
assertThat(ringBearers).hasEntrySatisfying(oneRing, character -> {
   assertThat(character.getRace()).isEqualTo(ELF);
});

Verifies that the actual Optional contains a value which satisfies the given Condition.

Example:

Condition<TolkienCharacter> isAnElf = new Condition<>(character -> character.getRace() == ELF, "an elf");

TolkienCharacter legolas = new TolkienCharacter("Legolas", 1000, ELF);
TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);

// assertion succeeds
assertThat(Optional.of(legolas)).hasValueSatisfying(isAnElf);

This is an alternative to JUnitSoftAssertions and AutoCloseableSoftAssertions to avoid having to call assertAll manually.

Example:

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   SoftAssertions.assertSoftly(softly -> {
      softly.assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
      softly.assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
      softly.assertThat(mansion.library()).as("Library").isEqualTo("clean");
      softly.assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
      softly.assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
      softly.assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
      softly.assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
      // no need to call assertAll, it is done by assertSoftly.
   });
}

Improves the allMatch iterable/array assertion error message by passing a description of the given predicate.

Assertion error message example:

List<TolkienCharacter> hobbits = newArrayList(frodo, sam, pippin, sauron);

// assertion fails (as expected) ...
assertThat(hobbits).allMatch(character -> character.getRace() == HOBBIT, "hobbits");
//... giving this error message:
java.lang.AssertionError:
Expecting all elements of:
  <[Frodo 33 years old Hobbit,
    Sam 38 years old Hobbit,
    Pippin 28 years old Hobbit,
    Sauron 50000 years old Maia]>
to match 'hobbits' predicate but this element did not:
  <Sauron 50000 years old Maia>

Release date : 2016-11-21

Many thanks to Class Augner, Pascal Schumacher, Mike Wilkes, Kseniya Panasyuk, Valeriy Vyrva, Chris Arnott, Gaël Lhez and Filip Hrisafov for their contributions.

  • Static fields should be ignored in field by field comparisons. (Mike Wilkes and Kseniya Panasyuk)
  • Add byLessThan as an alias of within/offset for number assertions.
  • usingComparatorForType now accepts registered type subclasses instead of only an exact type match. (Filip Hrisafov)
  • Limit the number of elements from an iterable/array/map that are printed in error messages to 1000. (Filip Hrisafov)
  • Add many missing tests. (Filip Hrisafov)
  • Provide @SafeVarargs for ListAssert and IterableAssert. (Gaël Lhez)
  • Remove usage of java.beans.Introspection to improve android compatibility. (Pascal Schumacher)
  • Javadoc improvements ! (mainly by Pascal Schumacher)
  • OSGI manifest contains unnecassary import and export packages.(Cristiano Gavião)
  • Increase priority of custom comparators in isEqualToComparingFieldByFieldRecursively so that custom comparators can be used for collection types and maps. (Pascal Schumacher)
  • containsExactly was broken when the used comparison strategy found duplicate elements.

fail methods have been added to soft assertions filling the gap with standard assertions.

Example :

SoftAssertions soft = new SoftAssertions();

soft.assertThat("foo").startsWith("boo");
assertThat(soft.errorsCollected()).hasSize(1);

soft.fail("Fail");
assertThat(soft.errorsCollected()).hasSize(2);

The new fail method allows to build the error message like String.format.

Example :

try {
  fail("I prefer %s over %s", "Batman", "Superman");
} catch (AssertionError e) {
  assertThat(e).hasMessage("I prefer Batman over Superman");
}

Add int based version of assertions that were taking byte parameters.

One example (amongst many new assertions) :

// before
assertThat(new byte[] { 1, 2, 3 }).contains((byte)1, (byte)2);
// after
assertThat(new byte[] { 1, 2, 3 }).contains(1, 2);

containsExactlyInAnyOrder was initially added for iterable/object arrays, it is now available for primitive arrays. It verifies that the actual array contains exactly the given values and nothing else, in any order.

Example with int array :

// this containsExactlyInAnyOrder assertion succeeds
assertThat(new int[] { 1, 2, 1 }).containsExactlyInAnyOrder(1, 1, 2);

// whereas containsExactly fails given the same input as the order of values is different:
assertThat(new int[] { 1, 2, 1 }).containsExactly(1, 1, 2);

Verifies that the actual Throwable has a suppressed exception similar to the given one, that is with the same type and message (no use of the equals method).

Example:

Throwable throwable = new Throwable();
Throwable invalidArgException = new IllegalArgumentException("invalid argument");
throwable.addSuppressed(invalidArgException);

// These assertions succeed:
assertThat(throwable).hasSuppressedException(invalidArgException);
assertThat(throwable).hasSuppressedException(new IllegalArgumentException("invalid argument"));

// These assertions fail:
assertThat(throwable).hasSuppressedException(new IllegalArgumentException("invalid parameter"));
assertThat(throwable).hasSuppressedException(new NullPointerException());

Verifies that the actual Throwable has no suppressed exceptions.

Example:

Throwable throwable = new Throwable();

// this assertion succeeds
assertThat(new Throwable()).hasNoSuppressedExceptions();

// this one fails
throwable.addSuppressed(new IllegalArgumentException());
assertThat(throwable).hasNoSuppressedExceptions();

Verifies that the actual map contains a value for the given key that satisfies the given Condition.

Example:

Map<Ring, TolkienCharacter> ringBearers = new HashMap<>();
ringBearers.put(nenya, galadriel);
ringBearers.put(narya, gandalf);
ringBearers.put(vilya, elrond);
ringBearers.put(oneRing, frodo);

Condition<TolkienCharacter> elfBearer = new Condition<>(tc -> tc.getRace() == ELF, "an elf bearer");

// this assertion will pass
assertThat(ringBearers).hasEntrySatisfying(nenya, elfBearer);

// this assertion will fail
assertThat(ringBearers).hasEntrySatisfying(oneRing, elfBearer);

Verifies that the actual map contains at least one of the given entries.

Example:

Map<Ring, TolkienCharacter> ringBearers = new HashMap<>();
ringBearers.put(nenya, galadriel);
ringBearers.put(narya, gandalf);
ringBearers.put(vilya, elrond);
ringBearers.put(oneRing, frodo);

// assertion will pass
assertThat(ringBearers).containsAnyOf(entry(oneRing, frodo), entry(oneRing, sauron));

// assertion will fail
assertThat(ringBearers).containsAnyOf(entry(oneRing, gandalf), entry(oneRing, aragorn));

Verifies that the actual number is not close to the given one by less than the given offset. If the difference is equal to the offset value, the assertion fails.

Example with int:

import static org.assertj.core.api.Assertions.byLessThan;
import static org.assertj.core.api.Assertions.withinPercentage;

// assertions will pass:
assertThat(5).isNotCloseTo(7, byLessThan(1));
assertThat(11).isNotCloseTo(10, withinPercentage(5));

// assertions will fail
assertThat(5).isNotCloseTo(7, byLessThan(2));
assertThat(5).isNotCloseTo(7, byLessThan(3));
assertThat(11).isNotCloseTo(10, withinPercentage(10));
assertThat(11).isNotCloseTo(10, withinPercentage(20));

Verifies that the actual CharSequence is blank, i.e. that it contains only whitespace characters. There are two variations of this assertion: isJavaBlank with whitespace defined by java Character#isWhitespace(char) and isBlank with whitespace defined according to the latest Unicode standard.

isNotBlank is (obviously) the opposite assertion of isBlank.

Examples:

 // these assertions succeed:
assertThat(" ").isBlank();
assertThat("     ").isBlank();
assertThat("a").isNotBlank();
assertThat(" b").isNotBlank();
assertThat("").isNotBlank();
assertThat((String) null).isNotBlank();

// these ones fail:
assertThat("a").isBlank();
assertThat(" b").isBlank();
assertThat("").isBlank();
assertThat((String) null).isBlank();
assertThat(" ").isNotBlank();
assertThat("     ").isNotBlank();

Release date : 2016-07-17

Thanks to Cristiano Gavião for the fix.

  • Fix MANIFEST.MF that was importing ant packages. (Cristiano Gavião)

Release date : 2016-07-03

This release includes all changes from AssertJ core 2.5.0 and adds some specific to Java 8.

The 3.5.1 release fixes a regression of the Stream isEqualTo assertion which was changed in 3.5.0 to support reference comparison.

Thanks to Pascal Schumacher, Dima Gerasimov, tommyshem, Filip Hrisafov, Fabien Duminy and timmikk for their contributions.

  • Better cross OS line separator support in error messages. (timmikk)
  • Soft assertions output line numbers of failed assertions. (Pascal Schumacher, Fabien Duminy)
  • Javadoc improvements. (Pascal Schumacher, tommyshem)
  • Fix Stream assertions relying on checking the original stream (ex: isSameAs).

The following Predicate assertions are available:

  • accepts(T... values) : succeeds if all given values match the Predicate under test
  • rejects(T... values) : succeeds if no given value matches the Predicate under test
  • acceptsAll(Iterable) : succeeds if all elements of the given Iterable match the Predicate under test
  • rejectsAll(Iterable) : succeeds if no elements of the given Iterable match the Predicate under test

Example : accepts & acceptsAll

Predicate<String> ballSportPredicate = sport -> sport.contains("ball");

// assertion succeeds:
assertThat(ballSportPredicate).accepts("football")
                              .accepts("football", "basketball", "handball");
assertThat(ballSportPredicate).acceptsAll(list("football", "basketball", "handball"));

// assertion fails because of curling :p
assertThat(ballSportPredicate).accepts("curling")
assertThat(ballSportPredicate).accepts("football", "basketball", "curling");
assertThat(ballSportPredicate).acceptsAll(list("football", "basketball", "curling"));

Example : rejects & rejectsAll

Predicate<String> ballSportPredicate = sport -> sport.contains("ball");

// assertion succeeds:
assertThat(ballSportPredicate).rejects("curling")
                              .rejects("curling", "judo", "marathon");
assertThat(ballSportPredicate).rejectsAll(list("curling", "judo", "marathon"));

// assertion fails because of football:
assertThat(ballSportPredicate).rejects("football");
assertThat(ballSportPredicate).rejects("curling", "judo", "football");
assertThat(ballSportPredicate).rejectsAll(list("curling", "judo", "football"));

Verifies that the actual object satisfied the given requirements expressed as a Consumer<T>.

This is useful to perform a group of assertions on multiple objects or to avoid having to declare a local variable in order to use multiple assertions on a single object.

Example :

// second constructor parameter is the light saber color
Jedi yoda = new Jedi("Yoda", "Green");
Jedi luke = new Jedi("Luke Skywalker", "Green");

Consumer<Jedi> jediRequirements = jedi -> {
   assertThat(jedi.getLightSaberColor()).isEqualTo("Green");
   assertThat(jedi.getName()).doesNotContain("Dark");
};

// assertions succeed:
assertThat(yoda).satisfies(jediRequirements);
assertThat(luke).satisfies(jediRequirements);

// assertions fails:
Jedi vader = new Jedi("Vader", "Red");
assertThat(vader).satisfies(jediRequirements);

In the following example, satisfies allows multiple assertions without the declaration of a local variable:

// no need to define team.getPlayers().get(0).getStats() as a local variable
assertThat(team.getPlayers().get(0).getStats()).satisfies(stats -> {
   assertThat(stats.pointPerGame).isGreaterThan(25.7);
   assertThat(stats.assistsPerGame).isGreaterThan(7.2);
   assertThat(stats.reboundsPerGame).isBetween(9, 12);
};

Assertions error messages use a Representation to format the different types involved. By using registerFormatterForType you can control the formatting of a given type by providing a specific formatter.

Registering a formatter makes it available to all of AssertJs representations:
  • StandardRepresentation
  • UnicodeRepresentation
  • HexadecimalRepresentation
  • BinaryRepresentation

Example :

// without specific formatter
assertThat(STANDARD_REPRESENTATION.toStringOf(123L)).isEqualTo("123L");

// register a formatter for Long
Assertions.registerFormatterForType(Long.class, value -> "$" + value + "$");

// now Longs will be formatted between $ in error messages
assertThat(STANDARD_REPRESENTATION.toStringOf(longNumber)).isEqualTo("$123$");

// The following assertion fails ...
assertThat(123L).isEqualTo(456L);
// ... with error :
expected:<$456$> but was:<$123$>

Verifies that the iterable/array contains only a single element and that the element satisfies the given assertions expressed as a Consumer. If it does not, only the first error is reported (use SoftAssertions to get all errors).

Example :

List<Jedi> jedis = asList(new Jedi("Yoda", "red"));

// assertions will pass
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> assertThat(yoda.getName()).startsWith("Y"));

assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> {
 assertThat(yoda.getName()).isEqualTo("Yoda");
 assertThat(yoda.getLightSaberColor()).isEqualTo("red");
});

// assertion will fail
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> assertThat(yoda.getName()).startsWith("Vad"));

// fails as one the assertions is not satisfied
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> {
 assertThat(yoda.getName()).isEqualTo("Yoda");
 assertThat(yoda.getLightSaberColor()).isEqualTo("purple");
});

// fails but only reports the first error
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> {
 assertThat(yoda.getName()).isEqualTo("Luke");
 assertThat(yoda.getLightSaberColor()).isEqualTo("green");
});

// fails and reports all errors thanks to SoftAssertions
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> {
 SoftAssertions softly = new SoftAssertions();
 softly.assertThat(yoda.getName()).isEqualTo("Luke");
 softly.assertThat(yoda.getLightSaberColor()).isEqualTo("green");
 softly.assertAll();
});

jedis.add(new Jedi("Luke", "green"));

// fails : the given assertion requirements are met but there are too many jedis !
assertThat(jedis).hasOnlyOneElementSatisfying(yoda -> assertThat(yoda.getName()).startsWith("Yo"));

Extracts multiple values from each Iterable's element according to the given Extractors and concatenates/flattens the extracted values into a list that is used as the new object under test.

If the extracted values were not flattened, instead of a simple list like (given 2 extractors) :

  element1.value1, element1.value2, element2.value1, element2.value2, ...

we would get a list of list like :

  list(element1.value1, element1.value2), list(element2.value1, element2.value2), ...

Example :

// fellowshipOfTheRing is a List<TolkienCharacter>

// values are extracted in order and flattened : age1, name1, age2, name2, age3 ...
assertThat(fellowshipOfTheRing).flatExtracting(TolkienCharacter::getAge,
                                               TolkienCharacter::getName)
                               .contains(33 ,"Frodo",
                                         1000, "Legolas",
                                         87, "Aragorn");

Release date : 2016-07-03

Special thanks to Pascal Schumacher for his contributions including relentless code cleanup and documentation, thanks mate !

Many thanks to Dima Gerasimov, Nick Stolwijk, Ben Blank, Fabien Duminy, James Strachan, Johannes Brodwall and Kevin Fang for their contributions.

  • Add CheckReturnValue to detect incorrect API usage of assertions in FindBugs. (Dima Gerasimov)
  • Add Java 6 soft assertions (Standard, BDD and JUnit style) for Android projects. (Kevin Fang)
  • Include Object assertions in Throwable ones.
  • A bunch of Javadoc improvements ! (most of them by Pascal Schumacher)
  • SoftAssertions were not handling nested calls correctly.
  • isEqualTo failed when given an Iterator.
  • assertSame and assertNotSame assertions were failing for Iterator. (Nick Stolwijk)
  • startsWith assertion did not work for infinite Iterators.
  • Add missing BDDAssertions entry point methods.
  • Add missing SoftAssertions entry point methods.

Extract specified properties/fields from each Iterable elements, group all of them into a single List that becomes the object under test.

Example :

Iterable<TolkienCharacter> fellowshipOfTheRing = ...

// flat extraction : all extracted values are put into a single list
assertThat(fellowshipOfTheRing).flatExtracting("name", "age", "race.name")
                               .contains("Boromir", 37, "Man",
                                         "Sam", 38, "Hobbit",
                                         "Legolas", 1000, "Elf");
// classic extraction :
// - needs a tuple to check values
// - stricter assertion -> using tuple("Legolas", 38, "Hobbit") would fail
assertThat(fellowshipOfTheRing).extracting("name", "age", "race.name")
                               .contains(tuple("Boromir", 37, "Man"),
                                         tuple("Sam", 38, "Hobbit"),
                                         tuple("Legolas", 1000, "Elf"));

The idea is to allow navigating to any Iterable element in order to perform assertions on it, which are Object assertions by default. If you want specific ones like String assertions you will have to provide the corresponding Assert class i.e. StringAssert (the reason being Java generics limitations).

Possible navigations:

  • first()
  • last()
  • element(index)

Navigating back to the Iterable is not supported.

Examples :

Iterable<String> hobbitsNames = newArrayList("frodo", "sam", "pippin");

// Object assertions only (due to Java generics limitations)
assertThat(hobbitsNames).first()
                        .isEqualTo("frodo");
assertThat(hobbitsNames).element(1)
                        .isEqualTo("sam");
assertThat(hobbitsNames).last()
                        .isEqualTo("pippin");

// String assertions are possible if you specify the assert class
assertThat(hobbitsNames, StringAssert.class).first()
                                            .startsWith("fro")
                                            .endsWith("do");
assertThat(hobbitsNames, StringAssert.class).element(1)
                                            .contains("a");
assertThat(hobbitsNames, StringAssert.class).last()
                                            .endsWith("in");

It is now possible to navigate to an Iterable's size, perform Integer assertions on it and then navigate back to the Iterable to chain other assertions.

Example : instead of ...

Iterable<Ring> elvesRings = newArrayList(vilya, nenya, narya);

// can't chain size assertions with Iterable ones
assertThat(elvesRings.size()).isGreaterThan(1)
                             .isLessThanOrEqualTo(3)
assertThat(elvesRings).contains(narya)
                      .doesNotContain(oneRing);

... you can now write:

// all Integer assertions are available after size()
assertThat(elvesRings).size()
                         .isGreaterThan(1)
                         .isLessThanOrEqualTo(3)
                      .returnToIterable()
                         .contains(narya)
                         .doesNotContain(oneRing);

It is now possible to navigate to a Map's size, perform Integer assertions on it and then navigate back to the Map to chain other assertions.

Example : instead of ...

Map<Ring TolkienCharacter> ringBearers = new HashMap<>();
ringBearers.put(nenya, galadriel);
ringBearers.put(narya, gandalf);
ringBearers.put(oneRing, frodo);

// can't chain size assertions with Map ones
assertThat(ringBearers.size()).isGreaterThan(1)
                              .isLessThanOrEqualTo(3)
assertThat(ringBearers).containsKeys(oneRing, nenya, narya)
                       .containsEntry(oneRing, frodo);

... you can now write:

// all Integer assertions are available after size()
assertThat(ringBearers).size()
                          .isGreaterThan(1)
                          .isLessThanOrEqualTo(3)
                       .returnToMap()
                          .containsKeys(oneRing, nenya, narya)
                          .containsEntry(oneRing, frodo);

AssertJ relies on a Representation object to format types in error messages. Users can now register their own Representation either per assertion or globally (i.e. for all future assertions error messages).

  • global scope : Assertions.useRepresentation(myRepresentation)
  • per assertion scope : assertThat(actual).withRepresentation(myRepresentation)

Examples :

private class Example {} // dummy class

private class CustomRepresentation extends StandardRepresentation {

  // override needed to hook non predefined type formatting
  @Override
  public String toStringOf(Object o) {
    if (o instanceof Example) return "Example";
    // fallback to default formatting.
    return super.toStringOf(o);
  }

  // override a predefined type formatting : String
  @Override
  protected String toStringOf(String str) {
    return "$" + str + "$";
  }
}

Global scope custom representation :

// register CustomRepresentation only once
Assertions.useRepresentation(new CustomRepresentation());

// this assertion fails ...
assertThat(new Example()).isNull();
// ... with error :
expected:<[null]> but was:<[Example]>

// this one fails ...
assertThat("foo").startsWith("bar");
// ... with error :
Expecting:
  <$foo$>
to start with:
  <$bar$>

Per assertion scope custom representation :

// we need to register CustomRepresentation for each assertions
 Representation customRepresentation = new CustomRepresentation();

// this assertion fails ...
assertThat(new Example()).withRepresentation(customRepresentation)
                         .isNull();
// ... with error :
expected:<[null]> but was:<[Example]>

// this one fails ...
assertThat("foo").withRepresentation(customRepresentation)
                 .startsWith("bar");
// ... with error :
Expecting:
  <$foo$>
to start with:
  <$bar$>

Verifies that the actual object has no Null fields or properties (inherited ones are taken into account) except the given ones (if any).

Example :

// all TolkienCharacter fields are set
TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);
assertThat(frodo).hasNoNullFieldsOrProperties();

// 'name' fields is not set
TolkienCharacter hobbitWithoutName = new TolkienCharacter(null, 38, HOBBIT);
assertThat(hobbitWithoutName).hasNoNullFieldsOrPropertiesExcept("name");

Several assertions related to URL and URI parameters have been added:

  • hasParameter(name) : verify that an URL/URI has the given parameter
  • hasParameter(name, value) : verify that an URL/URI has the given parameter with the given value
  • hasNoParameter(name) : verify that an URL/URI does not have the given parameter
  • hasNoParameter(name, value) : verify that an URL/URI does not have the given parameter with the given value
  • hasNoParameters() : verify that an URL/URI has not parameters at all

Examples :

// check parameter presence
assertThat(new URL("http://www.helloworld.org/index.html?happy")).hasParameter("happy");
assertThat(new URL("http://www.helloworld.org/index.html?happy=very")).hasParameter("happy");

// check parameter presence with expected value
assertThat(new URL("http://www.helloworld.org/index.html?happy")).hasParameter("happy", null);
assertThat(new URL("http://www.helloworld.org/index.html?happy=very")).hasParameter("happy", "very");

// check the absence of parameters
assertThat(new URL("http://www.helloworld.org/index.html")).hasNoParameters();

// check the absence of given parameter
assertThat(new URL("http://www.helloworld.org/index.html")).hasNoParameter("happy");
assertThat(new URL("http://www.helloworld.org/index.html")).hasNoParameter("happy", "very");

// check the absence of given parameter with the given value
assertThat(new URL("http://www.helloworld.org/index.html?happy")).hasNoParameter("happy", "very");
assertThat(new URL("http://www.helloworld.org/index.html?happy=very")).hasNoParameter("happy", null);

Use a recursive field/property by field/property comparison (including inherited fields/properties) instead of relying on actual type equals method to compare iterable/array elements for incoming assertion checks.

The recursive property/field comparison is not applied on fields having a custom equals implementation, i.e. the overridden equals method will be used instead of a field/property by field/property comparison.

The recursive comparison handles cycles.

You can specify a custom comparator per (nested) name or type of element field with usingComparatorForElementFieldsWithNames and usingComparatorForElementFieldsWithType.

The objects to compare can be of different types but must have the same properties/fields. For example if actual object has a name String field, the other object must also have one. If an object has a field and a property with the same name, the property value will be used over the field.

Example :

// setter, getters and constructor omitted
public class Dude {
  String name;
  double height;
  Dude friend;
}

Dude jon = new Dude("Jon", 1.2);
Dude sam = new Dude("Sam", 1.3);
// introduce object graph cycle by mutual friendship
jon.friend = sam;
sam.friend = jon;

Dude jonClone = new Dude("Jon", 1.2);
Dude samClone = new Dude("Sam", 1.3);
jonClone.friend = samClone;
samClone.friend = jonClone;

// succeeds as jon, sam are equal to jonClone, samClone "by value"
assertThat(asList(jon, sam)).usingRecursiveFieldByFieldElementComparator()
                            .contains(jonClone, samClone);

Allows to set a comparator to compare properties or fields of elements of an array/iterable with the given type.

Comparators need to be specified by usingComparatorForElementFieldsWithType before calling any of:

  • usingFieldByFieldElementComparator
  • usingElementComparatorOnFields
  • usingElementComparatorIgnoringFields
  • usingRecursiveFieldByFieldElementComparator

Comparators specified by usingComparatorForElementFieldsWithNames have precedence over specified by this method.

Example :

// setter, getters and constructor omitted
public class Dude {
  String name;
  double height;
}

Dude dude = new Dude("Frodo", 1.2);
Dude tallerDude = new Dude("Frodo", 1.3);
List<Dude> hobbits = asList(dude);

// double are considered equals if they are close by less than 0.5
Comparator<Double> closeEnough = new AtPrecisionComparator<>(0.5);

assertThat(hobbits).usingComparatorForElementFieldsWithType(closeEnough, Double.class)
                   .usingFieldByFieldElementComparator()
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithType(closeEnough, Double.class)
                   .usingElementComparatorOnFields("height")
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithType(closeEnough, Double.class)
                   .usingElementComparatorIgnoringFields("name")
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithType(closeEnough, Double.class)
                   .usingRecursiveFieldByFieldElementComparator()
                   .contains(tallerDude);

Dude reallyTallDude = new Dude("Frodo", 1.9);
// assertion FAILS : 1.9 - 1.2 > 0.5
assertThat(asList(dude)).usingComparatorForElementFieldsWithType(closeEnough, Double.class)
                        .usingFieldByFieldElementComparator()
                        .contains(reallyTallDude);

Allows to set a comparator to compare properties or fields of elements of an array/iterable with the given names.

Comparators need to be specified by usingComparatorForElementFieldsWithNames before calling any of:

  • usingFieldByFieldElementComparator
  • usingElementComparatorOnFields
  • usingElementComparatorIgnoringFields
  • usingRecursiveFieldByFieldElementComparator

Comparators specified by this method have precedence over those by usingComparatorForElementFieldsWithType.

Example :

// setter, getters and constructor omitted
public class Dude {
  String name;
  double height;
}

Dude dude = new Dude("Frodo", 1.2);
Dude tallerDude = new Dude("Frodo", 1.3);
List<Dude> hobbits = asList(dude);

// double are considered equals if they are close by less than 0.5
Comparator<Double> closeEnough = new AtPrecisionComparator<>(0.5);

// assertions will pass
assertThat(hobbits).usingComparatorForElementFieldsWithNames(closeEnough, "height")
                   .usingFieldByFieldElementComparator()
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithNames(closeEnough, "height")
                   .usingElementComparatorOnFields("height")
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithNames(closeEnough, "height")
                   .usingElementComparatorIgnoringFields("name")
                   .contains(tallerDude);

assertThat(hobbits).usingComparatorForElementFieldsWithNames(closeEnough, "height")
                   .usingRecursiveFieldByFieldElementComparator()
                   .contains(tallerDude);


Dude reallyTallDude = new Dude("Frodo", 1.9);
// assertion FAILS : 1.9 - 1.2 > 0.5
assertThat(asList(dude)).usingComparatorForElementFieldsWithNames(closeEnough, "height")
                        .usingFieldByFieldElementComparator()
                        .contains(reallyTallDude);

isBetween verifies that the actual value is in the [start, end] range (start included, end included).

isStrictlyBetween verifies that the actual value is in the ]start, end[ range (start excluded, end excluded).

Example :

// assertions succeed :
assertThat('b').isBetween('a', 'b');
assertThat('b').isBetween('a', 'c');
assertThat('b').isStrictlyBetween('a', 'c');

// assertions fail :
assertThat('a').isStrictlyBetween('a', 'b');
assertThat('b').isStrictlyBetween('a', 'b');

The result of last soft assertion is now available from the method wasSuccess(). It can be used to decide what the next assertion should be. One noteworthy usage is to check the presence of some value before verifying it.

Example :

SoftAssertions soft = new SoftAssertions();

Person person = ... // query one Person

if (soft.assertThat(person).isNotNull().wasSuccess()) {
    soft.assertThat(person.getAddress()).isNotNull();
}

Soft assertions acccumulated errors are now available with method errorsCollected().

Example :

SoftAssertions soft = new SoftAssertions();

soft.assertThat("foo").startsWith("boo");
assertThat(soft.errorsCollected()).hasSize(1);

soft.assertThat("bar").startsWith("far");
assertThat(soft.errorsCollected()).hasSize(2);

Release date : 2016-04-10

Thanks to Pascal Schumacher for his contribution.

  • Fix CodeGenerationException exception when using soft assertions with Comparable objects.
  • Fix syntax of some throwable javadoc examples. (Pascal Schumacher)

Release date : 2016-03-30

This release includes all changes from AssertJ core 2.4.0 and adds some specific to Java 8.

Thanks to Pascal Schumacher and Grzegorz Piwowarek for their contributions.

  • Better error message for Optional#shouldContain assertion. (Grzegorz Piwowarek)
  • Make AbstractZonedDateTimeAssert constructor protected to allow extension.
  • Javadoc improvements. (Pascal Schumacher)

isNotPresent is simply an alias of isEmpty assertion.

Example :

// assertion succeeds
assertThat(Optional.empty()).isNotPresent();

// assertion fails
assertThat(Optional.of("something")).isNotPresent();

isNotEmpty is simply an alias of isPresent assertion.

Example :

// assertion succeeds
assertThat(Optional.of("something")).isNotEmpty();

// assertion fails
assertThat(Optional.empty()).isNotEmpty();

withStackTraceContaining is used when starting exception assertions with assertThatExceptionOfType, it's an alternative of hasStackTraceContaining.

Example :

Throwable runtime = new RuntimeException("no way",
                                          new Exception("you shall not pass"));
 // assertion will pass
 assertThatExceptionOfType(RuntimeException.class)
           .isThrownBy(() -> {throw runtime;})
           .withStackTraceContaining("you shall not pass");

Release date : 2016-03-28

Special thanks to Pascal Schumacher for his contributions including relentless code cleanup and documentation, thanks buddy !
Many thanks also to Michaël Bitard, Michael W. Fender, Lovro Pandzic, Peter Phillips and Daniel Zlotin for their contributions.

Recursive comparison is based on java-util deepEquals by John DeRegnaucourt and Ken Partlow, thanks to them !

  • Better support for raw type assertions, specially Map and Iterable.
  • Add ComparableAssert and UrlAssert entry points to soft assertions. (Pascal Schumacher)
  • isCloseTo(expected, Percentage p) now accepts percentage values > 100%.
  • AbstractSoftAssertions exposes errorsCollected() to subclasses. (Michael W. Fender)
  • Ignore synthetic fields when comparing fields on an object. (Peter Phillips)
  • assertSameContentAs produces a better error message in case of MalformedInputException. (Michaël Bitard)
  • Remove unnecessary reference to java.nio.file.Path in order to improve Android compatibility.
  • A bunch of Javadoc improvements ! (Pascal Schumacher)
  • instanceOf assertions family was failing on Iterator.
  • isCloseTo(expected, Percentage p) did not work with negative expected values. (Pascal Schumacher)
  • Fix AssertJ's MapEntry that was not compatible with java.util.Map.Entry.
  • assertHasSameContentAs now uses the charset set by usingCharset to read the actual file/path. (Pascal Schumacher)
  • Fix OSGi export manifest to include repackaged cglib classes.

Assert that the object under test (actual) is equal to the given object based on recursive a property/field by property/field comparison (including inherited ones), the recursive property/field comparison is not applied on fields having a custom equals implementation, i.e. the overriden equals method will be used instead of a field by field comparison.

The recursive comparison handles cycle, by default it compares floats with a precision of 1.0E-6 and doubles with 1.0E-15.

You can specify a custom comparator per (nested) fields or type with respectively usingComparatorForFields(Comparator, String...) and usingComparatorForType(Comparator, Class).

The objects to compare can be of different types but must have the same properties/fields. For example if the actual object has a name String field, it is expected that the other object also has one. If an object has a field and a property with the same name, the property value will be used over the field.

Example :

// classes with public fields for brevity
public class Person {
  public String name;
  public double height;
  public Home home = new Home();
  public Person bestFriend;
  // constructor with name and height omitted for brevity's sake
}

public class Home {
  public Address address = new Address();
}

public static class Address {
  public int number = 1;
}

Person jack = new Person("Jack", 1.80);
jack.home.address.number = 123;

Person jackClone = new Person("Jack", 1.80);
jackClone.home.address.number = 123;

// cycle are handled in comparison
jack.bestFriend = jackClone;
jackClone.bestFriend = jack;

// will fail as equals compares object references
assertThat(jack).isEqualsTo(jackClone);

// jack and jackClone are equals when doing a recursive field by field comparison
assertThat(jack).isEqualToComparingFieldByFieldRecursively(jackClone);

// any type/field can be compared with a a specific comparator.
// let's change  jack's height a little bit
jack.height = 1.81;

// assertion fails because of the height difference
// (the default precision comparison for double is 1.0E-15)
assertThat(jack).isEqualToComparingFieldByFieldRecursively(jackClone);

// use usingComparatorForType to specify how to compare the given type
// assertion succeeds because we allow a 0.5 tolerance on double
assertThat(jack).usingComparatorForType(new DoubleComparator(0.5), Double.class)
                .isEqualToComparingFieldByFieldRecursively(jackClone);

// use usingComparatorForFields to specify how to compare some fields (nested fields are supported)
assertThat(jack).usingComparatorForFields(new DoubleComparator(0.5), "height")
                .isEqualToComparingFieldByFieldRecursively(jackClone);

Allows to set a specific comparator to compare properties or fields of the given type. A typical usage is for comparing numbers fields with a given precision. Comparators specified by usingComparatorForFields have precedence over comparators specified by this method.

Example :

public class TolkienCharacter {
  private String name;
  private double height;
  // boilerplate code omitted
}

TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 2.0);

Comparator<Double> closeEnough = new Comparator<Double>() {
  double precision = 0.5;
  public int compare(Double d1, Double d2) {
    return Math.abs(d1 - d2) <= precision ? 0 : 1;
  }
};

// assertions will pass
assertThat(frodo).usingComparatorForType(closeEnough, Double.class)
                 .isEqualToComparingFieldByField(tallerFrodo);

assertThat(frodo).usingComparatorForType(closeEnough, Double.class)
                 .isEqualToIgnoringNullFields(tallerFrodo);

assertThat(frodo).usingComparatorForType(closeEnough, Double.class)
                 .isEqualToIgnoringGivenFields(tallerFrodo);

assertThat(frodo).usingComparatorForType(closeEnough, Double.class)
                 .isEqualToComparingOnlyGivenFields(tallerFrodo);

// assertion will fail
assertThat(frodo).usingComparatorForType(closeEnough, Double.class)
                 .isEqualToComparingFieldByField(reallyTallFrodo);

Allows to set a specific comparator to compare properties or fields with the given names. A typical usage is for comparing double/float fields with a given precision. Comparators specified by this method have precedence over comparators specified by usingComparatorForType.

Example :

public class TolkienCharacter {
  private String name;
  private double height;
  // boilerplate code omitted
}

TolkienCharacter frodo = new TolkienCharacter("Frodo", 1.2);
TolkienCharacter tallerFrodo = new TolkienCharacter("Frodo", 1.3);
TolkienCharacter reallyTallFrodo = new TolkienCharacter("Frodo", 2.0);

Comparator<Double> closeEnough = new Comparator<Double>() {
  double precision = 0.5;
  public int compare(Double d1, Double d2) {
    return Math.abs(d1 - d2) <= precision ? 0 : 1;
  }
};

// assertions succeed (it is possible to specify multiple fields)
assertThat(frodo).usingComparatorForFields(closeEnough, "height")
                 .isEqualToComparingFieldByField(tallerFrodo);

assertThat(frodo).usingComparatorForFields(closeEnough, "height")
                 .isEqualToIgnoringNullFields(tallerFrodo);

assertThat(frodo).usingComparatorForFields(closeEnough, "height")
                 .isEqualToIgnoringGivenFields(tallerFrodo);

assertThat(frodo).usingComparatorForFields(closeEnough, "height")
                 .isEqualToComparingOnlyGivenFields(tallerFrodo);

// assertion fails
assertThat(frodo).usingComparatorForFields(closeEnough, "height")
                 .isEqualToComparingFieldByField(reallyTallFrodo);

Verifies that the content of the actual File/Path is the same as the given one, the expected File/Path being read with the given charset while the charset used to read the actual path can be provided with usingCharset(Charset/String)prior to calling this method; if not, the platform's default charset will be used.

Example :

Set<String> lines = Collections.singleton("Gerçek");

Path utf8File = Files.write(Paths.get("actual"), lines, StandardCharsets.UTF_8);
Charset turkishCharset = Charset.forName("windows-1254");
Path turkishFile = Files.write(Paths.get("expected"), lines, turkishCharset);

// The following assertion succeeds:
assertThat(utf8File).usingCharset(StandardCharsets.UTF_8)
                    .hasSameContentAs(turkishFile, turkishCharset);

// The following assertion fails:
assertThat(utf8File).usingCharset(StandardCharsets.UTF_8)
                    .hasSameContentAs(turkishFile, StandardCharsets.UTF_8);

Verifies that the actual group (Iterable or object array) contains exactly the given values and nothing else, in any order. The difference with containsOnly is that containsOnly does not enforce duplicates elements as containsExactlyInAnyOrder does.

Example :

// note that vilya appears twice
Iterable<Ring> elvesRings = newArrayList(vilya, nenya, narya, vilya);

// assertion succeeds as elements order does not matter
assertThat(elvesRings).containsExactlyInAnyOrder(vilya, vilya, nenya, narya);

// assertion fails as vilya is contained twice in elvesRings.
assertThat(elvesRings).containsExactlyInAnyOrder(nenya, vilya, narya);
// but containsOnly succeeds as it does not enforce duplicates elements
assertThat(elvesRings).containsOnly(nenya, vilya, narya);

Release date : 2016-01-10

This release includes all changes from AssertJ core 2.3.0 and additional ones specific to Java 8.

Thanks to Pascal Schumacher, Chris Arnott, Jeremy Landis, Trond Marius Øvstetun and Misha Brukman for their contributions.

  • Add Stream assertions.
  • Add allMatch to Iterable and Object[] assertions.
  • Add extracting with lambdas functions to Object[] assertions.
  • Add extracting feature with lambdas functions to Object assertions.
  • Allow performing multiple assertions on an Optional value with hasValueSatisfying. (Trond Marius Øvstetun)
  • Add isToday() to LocalDate assertion. (Chris Arnott)
  • Throwable assertion withMessage now supports String#format syntax.
  • Maven pom improvements. (Jeremy Landis and Pascal Schumacher)
  • Travis build status. (Misha Brukman)
  • More Javadoc code examples. (Pascal Schumacher)

assertThat(myStream) simply converts myStream to a List thus providing all List assertions.
Please note that the Stream is consumed and cannot be used again (unless you chain assertions).

Example :

Stream<TolkienCharacter> fellowshipOfTheRing = Stream.of(frodo, sam, pippin, boromir,
                                                         legolas, gandalf, gimli);
// all List assertion are available
assertThat(fellowshipOfTheRing).contains(frodo)
                               .doesNotContain(sauron);
                               .extracting(TolkienCharacter::getRace)
                               .contains(HOBBIT, ELF)
                               .doesNotContain(ORC);

// WARNING : this assertion is not possible as fellowshipOfTheRing was already consumed.
assertThat(fellowshipOfTheRing).contains(frodo);

Verifies that all elements of the actual Iterable or Object[] match the given Predicate.

Example :

// also works with hobbits defined as an Iterable<TolkienCharacter>
TolkienCharacter[] hobbits = { frodo, sam, pippin };

assertThat(hobbits).allMatch(character -> character.getRace() == HOBBIT);

It was already possible to extract multiple values by name (using introspection), it is now possible to pass lambda functions to extract the values to check.

Example :

TolkienCharacter[] fellowshipOfTheRing = { frodo, sam, pippin, boromir, legolas, gandalf, gimli };

// TolkienCharacter age is public
assertThat(fellowshipOfTheRingArray).extracting(TolkienCharacter::getName,
                                                tolkienCharacter -> tolkienCharacter.age)
                                    .contains(tuple("Boromir", 37),
                                              tuple("Sam", 38),
                                              tuple("Legolas", 1000));

It was already possible to extract multiple values by name (using introspection), it is now possible to pass lambda functions to extract the values to check.

Example :

TolkienCharacter[] fellowshipOfTheRing = { frodo, sam, pippin, boromir, legolas, gandalf, gimli };

// TolkienCharacter age is public
assertThat(fellowshipOfTheRingArray).extracting(TolkienCharacter::getName,
                                                tolkienCharacter -> tolkienCharacter.age)
                                    .contains(tuple("Boromir", 37),
                                              tuple("Sam", 38),
                                              tuple("Legolas", 1000));

Using lamdas functions, extract values from the object under test into an array, this new array becoming the object under test. (similar to extracting taking fields/properties names)

Example :

TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);

assertThat(frodo).extracting(TolkienCharacter::getName,
                             character -> character.age,
                             character -> character.getRace().getName())
                 .containsExactly("Frodo", 33, "Hobbit");

Verifies that the actual Optional contains a value and gives this value to the given Consumer for further assertions allowing deeper assertions on the containing object.

Example :

// one requirement
assertThat(Optional.of(10)).hasValueSatisfying(i -> { assertThat(i).isGreaterThan(9); });

// multiple requirements
assertThat(Optional.of("something")).hasValueSatisfying(s -> {
    assertThat(s).startsWith("some");
    assertThat(s).endsWith("thing");
    assertThat(s).isEqualTo("something");
});

// failing assertion as the Optional does not have a value.
assertThat(Optional.empty()).hasValueSatisfying(i -> { assertThat(i).isEqualTo("something"); });

Verifies that the actual LocalDate is today, that is matching current year, month and day.

Example :

 // assertion will pass
assertThat(LocalDate.now()).isToday();

// assertion will fail
assertThat(theFellowshipOfTheRin ReleaseDate()).isToday();

Some users prefer assertThatExceptionOfType over assertThatThrownBy to check exceptions, it is now possible to check the exception message specifying the expected value using String#format syntax.

Example :

assertThatExceptionOfType(IOException.class)
                 .isThrownBy(() -> { throw new Exception("boom !"); })
                 .withMessage("%s !", "boom");

Allow to check that an Optional value is the same as a given one.

Example :

Player ginobili = new Player("Manu Ginobili");
assertThat(Optional.of(ginobili)).containsSame(ginobili);

Release date : 2016-01-02

Special thanks to Pascal Schumacher for his contributions including relentless code cleanup and improvements, appreciated !
Many thanks also to Pierre Templier, Guillaume Husta, Libor Ondrušek, Dan Corder and Chris Arnott for their contributions.

This release tried to make AssertJ Core usable for testing Android applications (by introducing Java6Assertions) but this has not been reliably verified so any feedback is welcome.

AssertJ has used part of java-diff-utils code to produce better diff content, thanks to Dmitry Naumenko its creator !

  • isSubsetOf now supports array/varargs parameters. (Pascal Schumacher)
  • isIn and isNotIn now accept null values.
  • Add String#format syntax support to hasMessage Throwable assertion.
  • Better diff when comparing text content based on java-diff-utils. (Chris Arnott)
  • Add Java6Assertions entry point class to improve support for Android applications (feedback welcome).
  • assertIsEqualToIgnoringGivenFields does not require anymore the ignored fields to exist.
  • Field by field comparison learned to compare objects of different types.
  • When possible, maps are displayed sorted in error messages to ease diagnostics. (gagba)
  • Map assertions learned to use java.util.Map.Entry. (Pascal Schumacher)
  • BigDecimalComparator now handles null values.
  • To be OS agnostic, replace \n by %n in error messages. (Pascal Schumacher)
  • A bunch of Javadoc improvements ! (Pascal Schumacher and Chris Arnott)
  • Javadoc : clarify as() usage.
  • filteredOn was not working with Soft assertions.
  • containsSequence String assertion failed when given multiples of the same String.
  • OSGi : export all packages needed by other AssertJ libraries.

Extract the values of given fields/properties from the object under test into an array, this new array becoming the object under test.

Example :

// Create frodo, setting its name, age and Race fields (Race having a name field)
TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);

// let's verify Frodo's name, age and race name:
assertThat(frodo).extracting("name", "age", "race.name")
                 .containsExactly("Frodo", 33, "Hobbit");

hasFieldOrProperty : assert that the actual object has the specified field or property.

hasFieldOrPropertyWithValue : assert that the actual object has the specified field or property with the given value.

Example :

// Create frodo, setting its name, age and Race fields (Race having a name field)
TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);

// let's verify Frodo's age and race name:
assertThat(frodo).hasFieldOrProperty("age")
                 .hasFieldOrProperty("race.name")
                 .hasFieldOrPropertyWithValue("age", 33)
                 .hasFieldOrPropertyWithValue("race.name", "Hobbit");

Verifies that a String contains the given regular expression.

Example :

// you can use a Pattern or a String to define the regex to find.
assertThat("Frodo").containsPattern("Fr.d");
assertThat("Frodo").containsPattern(Pattern.compile("Fr.d"));

Verifies that the Map under test contains all entries of the given Map.

Example :

Map<Ring, TolkienCharacter> ringBearers = new HashMap<>();
ringBearers.put(nenya, galadriel);
ringBearers.put(narya, gandalf);
ringBearers.put(vilya, elrond);
ringBearers.put(oneRing, frodo);

Map<Ring, TolkienCharacter> elvesRingBearers = new HashMap<>();
elvesRingBearers.put(nenya, galadriel);
elvesRingBearers.put(narya, gandalf);
elvesRingBearers.put(vilya, elrond);

// assertion succeeds
assertThat(ringBearers).containsAllEntriesOf(elvesRingBearers);

All double[] and float[] assertions can now be performed with a given precision to compare numbers.

Example with contains assertion for double[]:

import static org.assertj.core.api.Assertions.withPrecision;

double[] values = new double[] { 1.0, 2.0, 3.0 };

// assertion succeeds
assertThat(values).contains(new double[] {1.01, 3.01, 2.0}, withPrecision(0.02));

// assertion fails
assertThat(values).contains(new double[] {1.0, 4.0}, withPrecision(0.5));

Note that you can also use usingComparatorWithPrecision to achieve the same result:

double[] values = new double[] { 1.0, 2.0, 3.0 };

// assertion succeeds
assertThat(values).usingComparatorWithPrecision(0.5)
                  .contains(1.1, 2.1);

Verifies that the Iterable under test contains a subset of the given values.

Example :

List<Ring> elvesRings = newArrayList(vilya, nenya, narya);

// assertion succeeds
assertThat(elvesRings).isSubsetOf(oneRing, vilya, nenya, narya);

Verifies the message of an Exception using String#format syntax.

Example :

try {
  List<String> abc = newArrayList("a", "b", "c");
  abc.get(4);
} catch (Exception e) {
  assertThat(e).hasMessage("Index: %s, Size: %s", 4, 3);
}

Files (or InputStreams) content comparison is smarter, much like version control diff thanks to java-diff-utils.

Example :

// writeFile takes file name and file content parameters
File actual = writeFile("actual.txt", "aaaaaa\n" +
                                      "bbbbbb\n" +
                                      "cccccc\n" +
                                      "dddddd\n");

File expected = writeFile("expected.txt", "------\n" +
                                          "aaaaaa\n" +
                                          "bbbbbb\n" +
                                          "CCCCCC\n" +
                                          "dddddd\n" +
                                          "eeeeee\n");

// assertion fails
assertThat(actual).hasSameContentAs(expected);

The previous assertion fails with the following error message:

File:
  <.../actual>
and file:
  <.../expected>
do not have same content:

Missing content at line 1:
  ["------"]

Changed content at line 4:
expecting:
  ["CCCCCC"]
but was:
  ["cccccc"]

Missing content at line 6:
  ["eeeeee"]

Release date : 2015-09-21

This release includes all changes from AssertJ core 2.2.0 and additional ones specific to Java 8.

Thanks to Richard Lucas, Tobias Bieniek, Clément Mathieu and Nicolai Parlog for their contributions.

  • Rename StrictAssertions to AssertionsForClassTypes.
  • Reintroduce Assertions providing all AssertJ methods - in case of ambiguous assertThat resolution, use either AssertionsForInterfaceTypes or AssertionsForClassTypes.
  • Better looking Javadoc.
  • More Javadoc code examples.
  • Add missing assertThatThrownBy and catchThrowable to WithAssertions. (Clément Mathieu)

Provide assertions for Java 8 CompletableFuture.

Note that hasFailed() is a shortcut for isCompletedExceptionally() and isNotCancelled().

Example :

// completed future
CompletableFuture<String> completedFuture = CompletableFuture.completedFuture("something");
assertThat(completedFuture).isCompleted()
                           .isCompletedWithValue("something")
                           .isCompletedWithValueMatching(val -> val.startsWith("some"))
                           .isDone();
// cancelled future
CompletableFuture<?> cancelledFuture = new CompletableFuture<>();
cancelledFuture.cancel(true);
assertThat(cancelledFuture).isCancelled()
                           .isDone()
                           .hasNotFailed();

// future completed exceptionally
CompletableFuture<?> futureExplosion = new CompletableFuture<>();
futureExplosion.completeExceptionally(new RuntimeException("boom !"));
assertThat(futureExplosion).isCompletedExceptionally()
                           .isDone();

// failed future = isCompletedExceptionally() + isNotCancelled()
assertThat(futureExplosion).hasFailed()
                           .hasFailedWithThrowableThat() // allow to chain exception assertions
                               .isInstanceOf(RuntimeException.class)
                               .hasMessage("boom !");

Provide like contains a way to check Optional value.

Example :

assertThat(Optional.of("Yoda")).hasValue("Yoda");
// same assertion using contains
assertThat(Optional.of("Yoda")).contains("Yoda");

Provide a way to check Optional value with a specific comparator.

Example :

// comparator implementation omitted
Comparator<String> caseInsensitiveStringComparator = ...;

assertThat(Optional.of("YODA")).usingValueComparator(caseInsensitiveStringComparator)
                               .hasValue("yoda");

Allow to check that an Optional value is the same as a given one.

Example :

Player ginobili = new Player("Manu Ginobili");
assertThat(Optional.of(ginobili)).containsSame(ginobili);

Release date : 2015-09-03

Thanks to Libor Ondrušek, Pascal Schumacher and Alexander Bischof for their contributions.

  • objects "field by field" comparison is now performed on property first then field (should be a minor breaking change !).
  • Add hasMessageMatching to throwable assertions. (Libor Ondrušek)
  • Add withFailMessage as an alternative to overridingErrorMessage. (Alexander Bischof)
  • Add isSubstringOf to String assertions.
  • Add Comparable assertions to Path as Path implements Comparable.
  • MapEntry key and value formatting is now consistent with AssertJ format representation. (Libor Ondrušek)
  • Deprecate isWithinXXX date assertions in favor of hasXXXField. (Alexander Bischof)
  • containsOnly error does not display elements not found section anymore if there no elements not found to display.
  • Better spacing in Javadoc code examples. (Pascal Schumacher)
  • Javadoc fixes : typos and dead links. (Pascal Schumacher)
  • Path's assertions should not rely on java.nio.Path.toFile(). (Pascal Schumacher)

Release date : 2015-06-25

This release include all changes from AssertJ core 2.1.0 and provides new ones specific to Java 8.

Thanks to Alexander Bischof, Mariusz Smykuła and Alban Dericbourg for their contributions.

  • Better looking Javadoc.
  • More Javadoc code examples.

AssertJ fluent filtering for collection/arrays has been improved to express the filter condition with a Predicate.

Example :

assertThat(fellowshipOfTheRing).filteredOn( character -> character.getName().contains("o") )
                               .containsOnly(aragorn, frodo, legolas, boromir);

Provide assertions for OffsetDateTime. Most of the assertions come with a String based parameter equivalent that will be parsed into a OffsetDateTime, the examples shown below use this possiblity for brevity sake's.

Examples :

OffsetDateTime firstOfJanuary2000InUTC = OffsetDateTime.parse("2000-01-01T00:00:00Z");

assertThat(firstOfJanuary2000InUTC).isEqualTo(OffsetDateTime.parse("2000-01-01T00:00:00Z"));
// same assertion but AssertJ takes care of expected String to OffsetDateTime conversion
assertThat(firstOfJanuary2000InUTC).isEqualTo("2000-01-01T00:00:00Z");

assertThat(firstOfJanuary2000InUTC).isAfter("1999-12-31T23:59:59Z");
// assertion succeeds as OffsetDateTime are compared in actual's time zone
// 2000-01-01T00:30:00+01:00 = 1999-12-31T23:30:00Z
assertThat(firstOfJanuary2000InUTC).isAfter("2000-01-01T00:30:00+01:00")
                                   .isAfterOrEqualTo("1999-12-31T23:59:59Z")
                                   .isAfterOrEqualTo("2000-01-01T00:00:00Z");

assertThat(firstOfJanuary2000InUTC).isBefore("2000-01-01T00:00:01Z")
                                   .isBeforeOrEqualTo("2000-01-01T00:00:01Z")
                                   .isBeforeOrEqualTo("2000-01-01T00:00:00Z");

OffsetDateTime offsetDateTime1 = OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC);
OffsetDateTime offsetDateTime2 = OffsetDateTime.of(2000, 1, 1, 23, 59, 59, 999, ZoneOffset.UTC);
OffsetDateTime offsetDateTime3 = OffsetDateTime.of(2000, 1, 1, 0, 59, 59, 999, ZoneOffset.UTC);
OffsetDateTime offsetDateTime4 = OffsetDateTime.of(2000, 1, 1, 0, 0, 59, 999, ZoneOffset.UTC);
OffsetDateTime offsetDateTime5 = OffsetDateTime.of(2000, 1, 1, 0, 0, 0, 999, ZoneOffset.UTC);
// comparison with a precision level
assertThat(offsetDateTime1).isEqualToIgnoringHours(offsetDateTime2);
assertThat(offsetDateTime1).isEqualToIgnoringMinutes(offsetDateTime3);
assertThat(offsetDateTime1).isEqualToIgnoringSeconds(offsetDateTime4);
assertThat(offsetDateTime1).isEqualToIgnoringNanos(offsetDateTime5);

Provide assertions for OffsetTime. Most of the assertions come with a String based parameter equivalent that will be parsed into a OffsetTime, the examples shown below use this possiblity for brevity sake's.

Examples :

OffsetTime oneAm = OffsetTime.parse("01:00:00+02:00");

assertThat(oneAm).isEqualTo("01:00:00+02:00");

assertThat(oneAm).isAfter("00:00:00+02:00")
                 .isAfterOrEqualTo("00:00:00+02:00")
                 .isAfterOrEqualTo("01:00:00+02:00");

assertThat(oneAm).isBefore("02:00:00+02:00")
                 .isBeforeOrEqualTo("02:00:00+02:00")
                 .isBeforeOrEqualTo("01:00:00+02:00");

Add assertions for OptionalInt, OptionalLong and OptionalDouble.

Examples :

OptionalInt optional = OptionalInt.of(12);
assertThat(optional).isPresent()
                    .hasValue(12);

OptionalDouble emptyOptional = OptionalDouble.empty();
assertThat(emptyOptional).isEmpty();

Allow to check the of type Optional value.

Example :

Optional optional = Optional.of("Test");
assertThat(optional).containsInstanceOf(String.class);

Release date : 2015-06-10

Thanks to Michal Kordas, Kamil Szymanski, Paul Dorzey and Alexander Bischof for their contributions.

  • Use strict instead of lenient date parsing by default, this might break few tests, if you really want to use lenient parsing just call Assertions.setLenientDateParsing(true).
  • Smart iterable/array formatting: display one element per line if overall description is too big (> 80 chars).
  • Deprecate hasContentEqualTo in favor of hasSameContentAs. (Alexander Bischof)
  • flatExtracting now accepts a String parameter to specify the (iterable/array) property to extract. (Alexander Bischof)
  • Add yyyy-MM-dd HH:mm:ss.SSS to default supported date formats in Date assertion using String parameter.
  • Field by field element comparators now support heterogeneous iterables (see this issue). (Paul Dorzey)
  • containsExactly assertion was not showing actual and expected if the error was that they had different sizes.
  • Display date with milliseconds to make error message understandable when two dates only differ by milliseconds.
  • Add usingFieldByFieldElementComparator, usingElementComparatorIgnoringFields and usingElementComparatorOnFields to ObjectArrayAssert
  • Additional code examples in Javadoc API.
  • Extraction of nested field/property failed when both field and property were combined.
  • containsOnly and containsExactly did not honor properly element comparison strategy.
  • OSGI Metadata did not include "core.data" in Export-Package.

It was already possible to filter iterable/array but not in current assertion flow, it is now possible to combine iterable/array assertion and filtering in a fluent way.

You can filter on a property/field or using a Condition.

Filtering on a property or a field

You specify first the property/field name to filter on and its expected value. The filter first tries to get the value from a property, then from a field. Reading private fields is supported by default, this can be globally disabled by calling Assertions.setAllowExtractingPrivateFields(false).

Filters supports reading nested property/field, not that if an intermediate value is null the whole nested property/field is considered to be null, thus reading "address.street.name" value will return null if "address.street" value is null.

Filters support basic operation : not, in, notIn

As an example, let's check all employees 800 years old :

Employee yoda   = new Employee(1L, new Name("Yoda"), 800);
Employee obiwan = new Employee(2L, new Name("Obiwan"), 800);
Employee luke   = new Employee(3L, new Name("Luke", "Skywalker"), 26);

List<Employee> employees = newArrayList(yoda, luke, obiwan);

// filter employees before performing an assertion
assertThat(employees).filteredOn("age", 800)
                     .containsOnly(yoda, obiwan);

// it supports nested property/field
assertThat(employees).filteredOn("name.first", "Luke")
                     .containsOnly(luke);

// to filter on null value just use filterOnNull
assertThat(employees).filteredOnNull("name.last")
                     .containsOnly(yoda, obiwan, noname);

Filters support basic operation : not, in, notIn

import static org.assertj.core.api.Assertions.in;
import static org.assertj.core.api.Assertions.not;
import static org.assertj.core.api.Assertions.notIn;
...

assertThat(employees).filteredOn("age", not(800))
                     .containsOnly(luke);

// Name is bean class with 'first' and 'last' String properties
assertThat(employees).filteredOn("name.first", in("Yoda", "Luke"))
                     .containsOnly(yoda, luke);

assertThat(employees).filteredOn("name.first", notIn("Yoda", "Luke"))
                     .containsOnly(obiwan);

You can chain filters :

// fellowshipOfTheRing is a list of TolkienCharacter having race and name fields
// 'not' filter is statically imported from Assertions.not
assertThat(fellowshipOfTheRing).filteredOn("race.name", "Man")
                               .filteredOn("name", not("Boromir"))
                               .containsOnly(aragorn);

Filtering with a Condition

Filter the iterable/array under test keeping only elements matching the given Condition.

As an example, let's check all employees whose age > 100 :

// old employee condition, "old employees" describes the condition in error message
// you just have to implement a 'matches' method
Condition<Employee> oldEmployees = new Condition<Employee>("old employees") {
      @Override
      public boolean matches(Employee employee) {
        return employee.getAge() > 100;
      }
  };

// use oldEmployees Condition to express filter predicate
assertThat(employees).filteredOn(oldEmployees)
                     .containsOnly(yoda, obiwan);

// You can combine Conditions with condition operators like Not:
assertThat(employees).filteredOn(not(oldEmployees))
                     .containsOnly(luke);

New assertions for URI and URL.

URI assertions examples :

assertThat(new URI("http://assertj.org:8080/news.html#print")).hasHost("assertj.org")
                                                              .hasPort(8080)
                                                              .hasPath("/news.html")
                                                              .hasFragment("print");
assertThat(new URI("http://assertj.org")).hasNoFragment()
                                         .hasNoPort()
                                         .hasPath("")
                                         .hasNoQuery()
                                         .hasNoUserInfo();

assertThat(new URI("mailto:java-net@java.sun.com")).hasNoPath();

assertThat(new URI("http://test:pass@www.helloworld.org/index.html")).hasUserInfo("test:pass");
assertThat(new URI("http://test@www.helloworld.org/index.html")).hasUserInfo("test");
assertThat(new URI("http://:pass@www.helloworld.org/index.html")).hasUserInfo(":pass");

URL assertions examples :

assertThat(new URL("http://assertj.org:8080/news.html#print")).hasHost("assertj.org")
                                                              .hasPort(8080)
                                                              .hasPath("/news.html")
                                                              .hasAnchor("print");
assertThat(new URL("http://assertj.org")).hasNoAnchor()
                                         .hasNoPath()
                                         .hasNoPort()
                                         .hasNoQuery()
                                         .hasNoUserInfo();

assertThat(new URL("http://helloworld.org")).hasAuthority("helloworld.org");

Verifies that the actual number is close to the given one within the given percentage.
If difference is equal to the percentage value, assertion is considered valid.

You can express percentage with Assertions.withinPercentage

Example :

import static org.assertj.core.api.Assertions.withinPercentage;
...

// assertions will pass:
assertThat(5.0).isCloseTo(6.0, withinPercentage(20.0));
assertThat(5).isCloseTo(6, withinPercentage(20));

// assertion will fail
assertThat(11).isCloseTo(10, withinPercentage(5));

Verifies that the actual value is equal to the given one by invoking Comparable.compareTo(Object).

isEqualByComparingTo verifies that the actual value is equal to the given one by invoking Comparable.compareTo(Object), isNotEqualByComparingTo does the opposite.

Example :

// assertion will pass because 8.0 is equal to 8.00 using BigDecimal.compareTo(BigDecimal)
assertThat(new BigDecimal("8.0")).isEqualByComparingTo(new BigDecimal("8.00"));

assertThat(new BigDecimal(1.0)).isNotEqualByComparingTo(new BigDecimal(2.0));

Verifies that the actual actual.toString() is equal to the given String.

Example :

CartoonCaracter homer = new CartoonCaracter("Homer");

// Instead of writing ...
assertThat(homer.toString()).isEqualTo("Homer");
// ... you can simply write:
assertThat(homer).hasToString("Homer");

Verifies that the actual Date represents the same time as the given date in String format.
It is the same assertion as hasSameTimeAs(Date) but given date is represented as String

Example :

Date date = parseDatetime("2003-04-26T12:00:00");

// assertion will pass
assertThat(date).hasSameTimeAs("2003-04-26T12:00:00");

// assertion will fail
assertThat(date).hasSameTimeAs("2003-04-26T12:00:01");
assertThat(date).hasSameTimeAs("2003-04-27T12:00:00");

Default date formats (expressed in the local time zone) are:

  1. yyyy-MM-dd'T'HH:mm:ss.SSS
  2. yyyy-MM-dd HH:mm:ss.SSS
  3. yyyy-MM-dd'T'HH:mm:ss
  4. yyyy-MM-dd

Verifies that the actual String does not start/end with the given String.

Example :

// assertions will pass
assertThat("Gandalf the grey").doesNotStartWith("grey");
                              .doesNotEndWith("Gan");

contains(Iterable)

Verifies that the actual String contains all the strings of the given Iterable.

Example :

assertThat("Gandalf the grey").contains(Arrays.asList("alf"));
assertThat("Gandalf the grey").contains(Arrays.asList("alf", "grey"));

containsSequence(Iterable)

Verifies that the actual String contains all the strings of the given Iterable in the Iterable iteration order.

Example :

assertThat("Gandalf the grey").contains(Arrays.asList("alf"));
assertThat("Gandalf the grey").contains(Arrays.asList("alf", "grey"));
Verifies that the actual String is equal to the given one, ignoring whitespace differences (mostly).
To be exact, the following whitespace rules are applied:
  • all leading and trailing whitespace of both actual and expected strings are ignored
  • any remaining whitespace, appearing within either string, is collapsed to a single space before comparison

Example :

// assertions will pass
assertThat("  my foo bar  ").isEqualToIgnoringWhitespace("my foo bar");
assertThat("my      foo bar").isEqualToIgnoringWhitespace("my foo bar");
assertThat(" my     foo bar ").isEqualToIgnoringWhitespace("my foo bar");
assertThat(" my\tfoo bar ").isEqualToIgnoringWhitespace(" my foo bar");
assertThat("my foo bar").isEqualToIgnoringWhitespace("   my foo bar   ");

// assertion will fail due to the space between foo and bar
assertThat(" my\tfoo bar ").isEqualToIgnoringWhitespace(" my foobar");

Verifies that the actual String is not equal to the given one, ignoring case considerations.

Example :

// assertion will pass
 assertThat("Gandalf").isNotEqualToIgnoringCase("Hobbit");

 // assertions will fail
 assertThat("Gandalf").isNotEqualToIgnoringCase("Gandalf");
 assertThat("Gandalf").isNotEqualToIgnoringCase("GaNDalf");

Iterable/array in error messages will be formatted on a single lines if the overall description is < 80 characters, otherwise it will formatted on multiple lines with one element per line.

You can set the line maxlength threshold with Assertions.setMaxLengthForSingleLineDescription

Example :

// this array ...
String[] greatBooks = array("A Game of Thrones", "The Lord of the Rings", "Assassin's Apprentice");
// ... is formatted on one line:
["A Game of Thrones", "The Lord of the Rings", "Assassin's Apprentice"]

// whereas this one ...
String[] greatBooks = array("A Game of Thrones", "The Lord of the Rings", "Assassin's Apprentice", "Guards! Guards! (Discworld)");
// ... is formatted on multiple lines (one element per line):
["A Game of Thrones",
 "The Lord of the Rings",
 "Assassin's Apprentice",
 "Guards! Guards! (Discworld)"]

Instead of having to implement an Extractor, you can use a String to specify the Iterable or array to extract and then flatten.

Example :

// the Simpsons
CartoonCharacter bart = new CartoonCharacter("Bart Simpson");
CartoonCharacter lisa = new CartoonCharacter("Lisa Simpson");
CartoonCharacter maggie = new CartoonCharacter("Maggie Simpson");
CartoonCharacter homer = new CartoonCharacter("Homer Simpson");
homer.addChildren(bart, lisa, maggie);
// the Flintstones
CartoonCharacter pebbles = new CartoonCharacter("Pebbles Flintstone");
CartoonCharacter fred = new CartoonCharacter("Fred Flintstone");
fred.getChildren().add(pebbles);

// extract children list and flatten them in one list
List<CartoonCharacter> parents = newArrayList(homer, fred);
assertThat(parents).flatExtracting("children")
                   .containsOnly(bart, lisa, maggie, pebbles);

Allow to check that a String contains only digit (but not that string is a valid number representation !).

Example :

// assertion will pass:
assertThat("321").containsOnlyDigits();

// assertion will fail:
assertThat("321.0").containsOnlyDigits();

Add isCloseTo primitive approximation assertion for long, int, short and byte, it relies on within method to express the allowed approximation which can be statically imported from org.assertj.core.api.Assertions.

Example :

import static org.assertj.core.api.Assertions.within;
...

// assertion will pass:
assertThat(5).isCloseTo(7, within(3));

// if difference is exactly equals to the offset, it's ok
assertThat(5).isCloseTo(7, within(2));

// assertion will fail:
assertThat(5).isCloseTo(7, within(1));

Verifies that the actual Class is final (has final modifier) or not.

Example :

assertThat(String.class).isFinal();
assertThat(Throwable.class).isNotFinal();

Release date : 2015-04-06

This is the first release that provides assertions for Java 8.

Thanks to Brice Dutheil, Jean-Christophe Gay, zdanek and Marcin Zajączkowski for their contributions.

  • AssertJ Core 3.0 relies on Java 8.
  • Condition can be defined with Predicate.
  • Add WithAssertions interface as an alternative to Assertions entry point.
  • Add more code examples in Javadoc API.

AssertJ provides assertions for ZonedDateTime, LocalDateTime, LocalDate and LocalTime. Most of the assertions come with a String based parameter equivalent that will be parsed into the expected date/time type, the examples shown below use this possiblity for brevity sake's.

Note that for ZonedDateTime assertions, comparison is performed in actual's time zone.

Comparing date/time ignoring some fields only checks that the non-ignored fields are equal. The ignored fields are those below (or equal) to the given precision, for example ignoring minutes means that minutes, seconds and nanoseconds will be ignored. It is also important to understand that the time difference does not count, it turns out that, as in the example below, two date/time can have only 1 ns difference with different minutes, seconds and nanoseconds fields.

LocalDateTime localDateTimeA = LocalDateTime.of(2000, 1, 1, 23, 50, 00, 000);
LocalDateTime localDateTimeB = LocalDateTime.of(2000, 1, 1, 23, 49, 59, 999999999);
// assertion fails as minute fields differ even if time difference is only 1ns
assertThat(localDateTimeA).isEqualToIgnoringSeconds(localDateTimeB);

LocalDate examples :

LocalDate firstOfJanuary2000 = LocalDate.parse("2000-01-01");

// AssertJ converts String parameters to LocalDate to ease writing expected LocalDate
assertThat(firstOfJanuary2000).isEqualTo("2000-01-01");

assertThat(firstOfJanuary2000).isAfter("1999-12-31")
                              .isAfterOrEqualTo("1999-12-31")
                              .isAfterOrEqualTo("2000-01-01");

assertThat(firstOfJanuary2000).isBefore("2000-01-02")
                              .isBeforeOrEqualTo("2000-01-02")
                              .isBeforeOrEqualTo("2000-01-01");

LocalTime examples :

LocalTime oneAm = LocalTime.parse("01:00:00");

// AssertJ converts String parameters to LocalTime to ease writing expected LocalTime
assertThat(oneAm).isEqualTo("01:00:00");

assertThat(oneAm).isAfter("00:00:00")
                 .isAfterOrEqualTo("00:00:00")
                 .isAfterOrEqualTo("01:00:00");

assertThat(oneAm).isBefore("02:00:00")
                 .isBeforeOrEqualTo("02:00:00")
                 .isBeforeOrEqualTo("01:00:00");

LocalDateTime examples :

LocalDateTime firstOfJanuary2000 = LocalDateTime.parse("2000-01-01T00:00:00");

// AssertJ converts String parameters to LocalDateTime to ease writing expected LocalDateTime
assertThat(firstOfJanuary2000).isEqualTo("2000-01-01T00:00:00");

assertThat(firstOfJanuary2000).isAfter("1999-12-31T23:59:59")
                              .isAfterOrEqualTo("1999-12-31T23:59:59")
                              .isAfterOrEqualTo("2000-01-01T00:00:00");

assertThat(firstOfJanuary2000).isBefore("2000-01-01T00:00:01")
                              .isBeforeOrEqualTo("2000-01-01T00:00:01")
                              .isBeforeOrEqualTo("2000-01-01T00:00:00");

// successful assertions ignoring ...
// ... nanoseconds
LocalDateTime localDateTime1 = LocalDateTime.of(2000, 1, 1, 0, 0, 1, 0);
LocalDateTime localDateTime2 = LocalDateTime.of(2000, 1, 1, 0, 0, 1, 456);
assertThat(localDateTime1).isEqualToIgnoringNanos(localDateTime2);
// ... seconds
localDateTime1 = LocalDateTime.of(2000, 1, 1, 23, 50, 0, 0);
localDateTime2 = LocalDateTime.of(2000, 1, 1, 23, 50, 10, 456);
assertThat(localDateTime1).isEqualToIgnoringSeconds(localDateTime2);
// ... minutes
localDateTime1 = LocalDateTime.of(2000, 1, 1, 23, 50, 0, 0);
localDateTime2 = LocalDateTime.of(2000, 1, 1, 23, 00, 2, 7);
assertThat(localDateTime1).isEqualToIgnoringMinutes(localDateTime2);
// ... hours
localDateTime1 = LocalDateTime.of(2000, 1, 1, 23, 59, 59, 999);
localDateTime2 = LocalDateTime.of(2000, 1, 1, 00, 00, 00, 000);
assertThat(localDateTime1).isEqualToIgnoringHours(localDateTime2);

ZonedDateTime examples :

ZonedDateTime firstOfJanuary2000InUTC = ZonedDateTime.parse("2000-01-01T00:00:00Z");

assertThat(firstOfJanuary2000InUTC).isEqualTo(ZonedDateTime.parse("2000-01-01T00:00:00Z"));
// same assertion but AssertJ takes care of expected String to ZonedDateTime conversion
assertThat(firstOfJanuary2000InUTC).isEqualTo("2000-01-01T00:00:00Z");
// example showing that ZonedDateTime are compared in actual's time zone
assertThat(firstOfJanuary2000InUTC).isEqualTo("2000-01-01T01:00:00+01:00");

assertThat(firstOfJanuary2000InUTC).isAfter("1999-12-31T23:59:59Z");
assertThat(firstOfJanuary2000InUTC).isAfter("2000-01-01T00:30:00+01:00"); // 1999-12-31T23:30:00Z
assertThat(firstOfJanuary2000InUTC).isAfterOrEqualTo("1999-12-31T23:59:59Z")
                                   .isAfterOrEqualTo("2000-01-01T00:00:00Z");

assertThat(firstOfJanuary2000InUTC).isBefore("2000-01-01T00:00:01Z")
                                   .isBeforeOrEqualTo("2000-01-01T00:00:01Z")
                                   .isBeforeOrEqualTo("2000-01-01T00:00:00Z");

// comparison with specific precision
ZonedDateTime zonedDateTime1 = ZonedDateTime.of(2000, 1, 1, 0,  0,  0,  0,   ZoneOffset.UTC);
ZonedDateTime zonedDateTime2 = ZonedDateTime.of(2000, 1, 1, 23, 59, 59, 999, ZoneOffset.UTC);
ZonedDateTime zonedDateTime3 = ZonedDateTime.of(2000, 1, 1, 0,  59, 59, 999, ZoneOffset.UTC);
ZonedDateTime zonedDateTime4 = ZonedDateTime.of(2000, 1, 1, 0,  0,  59, 999, ZoneOffset.UTC);
ZonedDateTime zonedDateTime5 = ZonedDateTime.of(2000, 1, 1, 0,  0,  0,  999, ZoneOffset.UTC);
assertThat(zonedDateTime1).isEqualToIgnoringHours(zonedDateTime2);
assertThat(zonedDateTime1).isEqualToIgnoringMinutes(zonedDateTime3);
assertThat(zonedDateTime1).isEqualToIgnoringSeconds(zonedDateTime4);
assertThat(zonedDateTime1).isEqualToIgnoringNanos(zonedDateTime5);

Use assertThatThrownBy(ThrowingCallable) to capture and then assert on a Throwable, ThrowingCallable being a functinonal interface it can be expressed by a lambda.

Example :

@Test
public void testException() {
   assertThatThrownBy(() -> { throw new Exception("boom!"); }).isInstanceOf(Exception.class)
                                                             .hasMessageContaining("boom");
}

BDD aficionados can separate when and then steps by using catchThrowable(ThrowingCallable) to capture the throwable and then perform assertions.

Example :

@Test
public void testException() {
   // given some preconditions

   // when
   Throwable thrown = catchThrowable(() -> { throw new Exception("boom!") };);

   // then
   assertThat(thrown).isInstanceOf(Exception.class)
                     .hasMessageContaining("boom");
}

Assertions for Optional have been added.

Examples :

// optional with value
Optional<String> optional = Optional.of("Test");
assertThat(optional).isPresent()
                    .contains("Test");
// empty optional
Optional<Object> emptyOptional = Optional.empty();
assertThat(emptyOptional).isEmpty();

matches assertion will succeed if the given Predicate passes. It is available for all objects.

Example :

TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);
// actual refers to frodo
assertThat(frodo).matches(actual -> actual.age > 30 && actual.getRace() == HOBBIT);

It was already possible to compare float, double and BigDecimal with a margin error, it's now possible to do the same thing with int, long, short and byte.

Examples :

// import static org.assertj.core.api.Assertions.within;
assertThat(30).isCloseTo(40, within(10));
assertThat(10l).isCloseTo(8l, within(2l));
assertThat((short)5).isCloseTo((short)7, within((short)3));
assertThat((byte)5).isCloseTo((byte)7, within((byte)3));

It is now easier to build a Condition, one just has to provide a predicate and a description (instead of having to extends Condition). You can specify the description using String.format syntax.

Example :

// build a Condition with a Predicate
Condition<String> fairyTale = new Condition<String>(s -> s.startsWith("Once upon a time"),
                                                    "a %s tale", "fairy");
String littleRedCap = "Once upon a time there was a dear little girl ...";
assertThat(littleRedCap).is(fairyTale);

Release date : 2015-03-07

This is a major release, the first that relies on Java 7.

Thanks to Brice Dutheil, Tobias Bieniek, Alexandre Balhier, Francis Galiegue, Lukasz Kryger, Tim Perry, Jean-Christophe Gay, Lovro Pandzic and Alexander Bischof for their contributions.

  • AssertJ Core 2.0 relies on Java 7.
  • To remove annoying warnings, @Varargs was added on methods using generics and varargs, this implied to make them final.
  • Field by field comparison compares private fields by default - this can be disabled with Assertions#setAllowComparingPrivateFields
  • Get rid of long time deprecated methods
  • containsExactly, containsOnly and containsOnlyKeys error messages don't show unexpected elements when there are none . (Alexandre Balhier)
  • isEqualToIgnoringGivenFields now verifies that the fields to ignore exist on the type of objects to compare. (Lukasz Kryger)
  • Allow to use private fields for field by field comparison. (Alexandre Balhier)
  • Make Map assertions more type safe with generics.
  • Complete ObjectArrayAssert with assertions added recently in IterableAssert.
  • Can use extracting with SoftAssertions. (Jean-Christophe Gay)
  • Add more code examples in Javadoc API.
  • IllegalFormatConversionException when using failWithMessage with '%d' placeholder.
  • Asserting Comparable did not provide access to ObjectAssert assertions.
  • containsExactly for arrays did not honor comparator set with usingElementComparator.

Assertions for Path, it provides the assertions that were defined for File and add some new ones specific to Path.

Note that some assertions have two versions: a normal one and a "raw" one (for instance, hasParent() and hasParentRaw()). The difference is that normal assertions will canonicalize or normalize the tested path and, where applicable, the path argument, before performing the actual test. Canonicalization includes normalization.

Canonicalization may lead to an I/O error if a path does not exist, in which case the given assertions will fail with a PathsException. Also note that symbolic links will be followed if the filesystem supports them. Finally, if a path is not absolute, canonicalization will resolve the path against the process' current working directory. .

Examples :

@Test
public void path_assertions() throws Exception {

   // Create a regular file, and a symbolic link pointing to it
   Path existingFile = Paths.get("somefile.txt");
   write(existingFile, "foo".getBytes());
   Path symlinkToExistingFile = Paths.get("symlink-to-somefile.txt");
   deleteIfExists(symlinkToExistingFile);
   createSymbolicLink(symlinkToExistingFile, existingFile);

   // Create a symbolic link whose target does not exist
   Path nonExistentPath = Paths.get("nonexistent");
   Path symlinkToNonExistentPath = Paths.get("symlinkToNonExistentPath");
   deleteIfExists(symlinkToNonExistentPath);
   createSymbolicLink(symlinkToNonExistentPath, nonExistentPath);

   // create directory and symlink to it
   Path dir = Paths.get("target/dir");
   deleteIfExists(dir);
   createDirectory(dir);
   Path dirSymlink = Paths.get("target", "dirSymlink");
   deleteIfExists(dirSymlink);
   createSymbolicLink(dirSymlink, dir.toAbsolutePath());

   // assertions examples
   assertThat(existingFile).exists();
   assertThat(symlinkToExistingFile).exists();
   assertThat(existingFile).existsNoFollowLinks();
   assertThat(symlinkToNonExistentPath).existsNoFollowLinks();

   assertThat(nonExistentPath).doesNotExist();

   assertThat(existingFile).isRegularFile();
   assertThat(symlinkToExistingFile).isRegularFile();

   assertThat(symlinkToExistingFile).isSymbolicLink();
   assertThat(dirSymlink).isDirectory().isSymbolicLink();
   assertThat(symlinkToNonExistentPath).isSymbolicLink();

   assertThat(dir).isDirectory();
   assertThat(dirSymlink).isDirectory();
   assertThat(dir).hasParent(Paths.get("target"))
                  .hasParent(Paths.get("target/dir/..")) // would fail with hasParentRaw
                  .hasParentRaw(Paths.get("target"));

   assertThat(existingFile.toRealPath()).isCanonical();

   assertThat(existingFile).hasFileName("somefile.txt");
   assertThat(symlinkToExistingFile).hasFileName("symlink-to-somefile.txt");

   // Unix specific assertions
   assertThat(Paths.get("/foo/bar")).isAbsolute();
   assertThat(Paths.get("foo/bar")).isRelative();
   assertThat(Paths.get("/usr/lib")).isNormalized();
   assertThat(Paths.get("a/b/c")).isNormalized();
   assertThat(Paths.get("../d")).isNormalized();
   assertThat(Paths.get("/")).hasNoParent();
   assertThat(Paths.get("foo")).hasNoParentRaw();
   assertThat(Paths.get("/usr/lib")).startsWith(Paths.get("/usr"))
                                    .startsWith(Paths.get("/usr/lib/..")) // would fail with startsWithRaw
                                    .startsWithRaw(Paths.get("/usr"));
   assertThat(Paths.get("/usr/lib")).endsWith(Paths.get("lib"))
                                    .endsWith(Paths.get("lib/../lib")) // would fail with endsWithRaw
                                    .endsWithRaw(Paths.get("lib"));
}
Date related :
  • useDateFormat : use registerCustomDateFormat instead.
  • withIsoDateFormat : use withDefaultDateFormatsOnly instead.
  • withDefaultDateFormats : use withDefaultDateFormatsOnly instead.
  • useIsoDateFormat : use useDefaultDateFormatsOnly instead.
  • useDefaultDateFormats : use useDefaultDateFormatsOnly instead.
Objects fields comparison related :
  • isLenientEqualsToByIgnoringNullFields : use isEqualToIgnoringNullFields instead.
  • isLenientEqualsToByAcceptingFields : use isEqualToComparingOnlyGivenFields instead.
  • isLenientEqualsToByIgnoringFields : use isEqualToIgnoringGivenFields instead.
  • isEqualsToByComparingFields : use isEqualToComparingFieldByField instead.
Others :
  • setAllowExtractingPrivateFields : use setAllowUsingPrivateFields instead.

Use assertThatThrownBy(ThrowingCallable) to capture and then assert on a Throwable.

Java 7 example :

assertThatThrownBy(new ThrowingCallable()

   @Override
   public void call() throws Exception {
     throw new Exception("boom!");
   }

 }).isInstanceOf(Exception.class)
   .hasMessageContaining("boom");

Java 8 example :

@Test
public void testException() {
   assertThatThrownBy(() -> { throw new Exception("boom!"); }).isInstanceOf(Exception.class)
                                                             .hasMessageContaining("boom");
}

BDD aficionados can separate when and then steps by using catchThrowable(ThrowingCallable) to capture the throwable and then perform assertions.

Java 7 example :

@Test
public void testException() {
   // when
   Throwable thrown = catchThrowable(new ThrowingCallable()

      @Override
      public void call() throws Exception {
         throw new Exception("boom!");
      }

   });
   // then
   assertThat(thrown).isInstanceOf(Exception.class)
                     .hasMessageContaining("boom");
}

Java 8 example :

@Test
public void testException() {
   // when
   Throwable thrown = catchThrowable(() -> { throw new Exception("boom!"); });

   // then
   assertThat(thrown).isInstanceOf(Exception.class)
                     .hasMessageContaining("boom");
}

To avoid having to call assertAll() at the end of your test methods, use AutoCloseableSoftAssertions with try-with-resources statement :

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   try (AutoCloseableSoftAssertions softly = new AutoCloseableSoftAssertions()) {
      // use SoftAssertions instead of direct assertThat methods
      softly.assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
      softly.assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
      softly.assertThat(mansion.library()).as("Library").isEqualTo("clean");
      softly.assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
      softly.assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
      softly.assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
      softly.assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
      // no need to call assertAll, it is done when softly is closed.
   }
}

Verifies that two Date/Timestamp correspond to the same time.
Example:

@Test
public void verify_that_date_and_timestamp_correspond_to_the_same_time() {
   Date date = new Date();
   Timestamp timestamp = new java.sql.Timestamp(date.getTime());
   assertThat(date).hasSameTimeAs(timestamp);
   assertThat(timestamp).hasSameTimeAs(date);
}

This assertion verifies that the actual map contains the given values.
Example:

Map<Ring, TolkienCharacter> ringBearers = ... // init with elves rings and the one ring

assertThat(ringBearers).containsValues(frodo, galadriel);

This assertion verifies that the actual map does not contain the given keys.
Example:

Map<Ring, TolkienCharacter> ringBearers = ... // init with elves rings only

assertThat(ringBearers).doesNotContainKeys(oneRing, someManRing);

This is useful when the object under test is a List but was declared as Object, in that case you can only have Object assertions, using asList() you will be able to use List assertions.
Example:

Object listAsObject = Arrays.asList(1, 2, 3);

// DOES NOT COMPILE as isSorted() is not an Object assertions
assertThat(listAsObject).isSorted();

// works as we have switched to List assertions
assertThat(listAsObject).asList().isSorted();

This is useful when the object under test is a String but was declared as Object, in that case you can only have Object assertions, using asString() you will be able to use String assertions.
Example:

Object stringAsObject = "hello world";

// DOES NOT COMPILE as contains() is not an Object assertions
assertThat(stringAsObject).contains("hello");

// works as we have switched to String assertions
assertThat(stringAsObject).asString().contains("hello");

Extracting is now able to extract values corresponding to the given keys.
Example:

 Employee yoda = new Employee(1L, new Name("Yoda"), 800);
 Employee luke = new Employee(2L, new Name("Luke"), 22);
 Employee han = new Employee(3L, new Name("Han"), 31);

 // build two maps
 Map<String, Employee> map1 = new HashMap<>();
 map1.put("key1", yoda);
 map1.put("key2", luke);

 Map<String, Employee> map2 = new HashMap<>();
 map2.put("key1", yoda);
 map2.put("key2", han);

 // instead of a list of objects, we have a list of maps
 List<Map<String, Employee>> maps = asList(map1, map2);

 // extracting a property in that case = get values from maps using property as a key
 assertThat(maps).extracting("key2").containsExactly(luke, han);
 assertThat(maps).extracting("key1").containsExactly(yoda, yoda);

 // it works with several keys, extracted values being wrapped in a Tuple
 assertThat(maps).extracting("key1", "key2").containsExactly(tuple(yoda, luke), tuple(yoda, han));

 // unknown keys leads to null (map behavior)
 assertThat(maps).extracting("bad key").containsExactly(null, null);

BDD soft assertions are like sot assertions but use then() instead of assertThat() to start assertions.

Note that JUnitBDDSoftAssertions and AutoCloseableSoftAssertions are also available, assertAll() being automatically called respectively by a JUnit rule or the implicit close method in a try-with-resources statement.

Example:

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   BDDSoftAssertions softly = new BDDSoftAssertions();
   softly.then(mansion.guests()).as("Living Guests").isEqualTo(7);
   softly.then(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
   softly.then(mansion.library()).as("Library").isEqualTo("clean");
   softly.then(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
   softly.then(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
   softly.then(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
   softly.then(mansion.professor()).as("Professor").isEqualTo("well kempt");
   // use JUnitBDDSoftAssertions or AutoCloseableSoftAssertions to avoid having to call assertAll()
   softly.assertAll();
}

Now upon running the test our JUnit exception message is far more detailed:

org.assertj.core.api.SoftAssertionError: The following 4 assertions failed:
 1) [Living Guests] expected:<[7]:> but was::<[6]>
 2) [Library] expected::<'[clean]'> but was::<'[messy]'>
 3) [Candlestick] expected::<'[pristine]'> but was::<'[bent]'>
 4) [Professor] expected::<'[well kempt]'> but was::<'[bloodied and disheveled]'>

If you call withThreadDumpOnError()before your assertions and an assertion error occurs, the thread dump will be printed on System.err.
Example:

assertThat("Messi").withThreadDumpOnError().isEqualTo("Ronaldo");

will print the thread dump, something looking like:

"JDWP Command Reader"
        java.lang.Thread.State: RUNNABLE

"JDWP Event Helper Thread"
        java.lang.Thread.State: RUNNABLE

"JDWP Transport Listener: dt_socket"
        java.lang.Thread.State: RUNNABLE

"Signal Dispatcher"
        java.lang.Thread.State: RUNNABLE

"Finalizer"
        java.lang.Thread.State: WAITING
                at java.lang.Object.wait(Native Method)
                at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
                at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
                at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:189)

"Reference Handler"
        java.lang.Thread.State: WAITING
                at java.lang.Object.wait(Native Method)
                at java.lang.Object.wait(Object.java:503)
                at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)

"main"
        java.lang.Thread.State: RUNNABLE
                at sun.management.ThreadImpl.dumpThreads0(Native Method)
                at sun.management.ThreadImpl.dumpAllThreads(ThreadImpl.java:446)
                at org.assertj.core.internal.Failures.threadDumpDescription(Failures.java:193)
                at org.assertj.core.internal.Failures.printThreadDumpIfNeeded(Failures.java:141)
                at org.assertj.core.internal.Failures.failure(Failures.java:91)
                at org.assertj.core.internal.Objects.assertEqual(Objects.java:314)
                at org.assertj.core.api.AbstractAssert.isEqualTo(AbstractAssert.java:198)
                at org.assertj.examples.ThreadDumpOnErrorExample.main(ThreadDumpOnErrorExample.java:28)

Verifies that the actual Throwable has a cause similar to the given one, that is with same type and message (it does not use equals method for comparison).
Example:

Throwable invalidArgException = new IllegalArgumentException("invalid arg");
Throwable throwable = new Throwable(invalidArgException);

// This assertion succeeds:
assertThat(throwable).hasCause(invalidArgException);

// These assertions fail:
assertThat(throwable).hasCause(new IllegalArgumentException("bad arg"));
assertThat(throwable).hasCause(new NullPointerException());
assertThat(throwable).hasCause(null); // prefer hasNoCause()

Release date : 2015-01-02

This is a minor release to support assertions for Iterable using bounded wildcard thanks to Johannes Schneider.

Example :

// note we use a bounded wildcard list
List<? extends BasketBallPlayer> bulls = newArrayList(rose, noah);

// did not compile in 1.7.0 but works in 1.7.1+
assertThat(bulls).contains(rose, noah);

Release date : 2014-10-04

Thanks to Mateusz Haligowski, Chris Arnott, Andrew Gaul, dmwvr, Alexandre Balhier, Adam Ruka, Mariusz Smykula and Marcin Mikosik for their contributions.

An unexpected breaking change has been discovered after 1.7.1 release, Comparable assertions prevent access to Object assertions like isEqualToComparingFieldByField, this issue will be fixed in 2.0.

  • assertThat(Iterator) does not consume iterator when it is not needed. (Marcin Mikosik)
  • Text content comparison differences report starts counting line count at 1 instead of 0. (Alexandre Balhier)
  • Better assertEqualContent error message when failing to compare InputStreams. (Andrew Gaul)
  • assertThat and then now return abstract assertion types to ease extending AssertJ core assertions. (Adam Ruka)
  • Various Javadoc API improvements.
  • Extracting now returns null value in extracted tuple if nested field/property is null.
  • Fix nested field value extraction in FieldSupport.
  • Field by field element comparison semantics were not honoured in basic assertions.
  • Fixes misleading error message in isAfterYear and isBeforeYear assertions.
  • BigDecimal assertions relies on compareTo semantics consistently (except for isEqualTo).
  • propertyValueOf(String propertyName, Object target, Class<T> clazz) was not supporting nested property value extraction.

Thanks to Mateusz Haligowski, you can now use a type safe extracting feature, you only have to implement the Extractor interface to define what you are extracting.
Example:

// extract 'age' field values
assertThat(fellowshipOfTheRing).extracting(age()).contains(33, 38, 36);

// extracting works also with user's types (here Race)
assertThat(fellowshipOfTheRing).extracting(race()).contains(HOBBIT, ELF)
                                                  .doesNotContain(ORC);
// extract 'name' and 'age' values.
assertThat(fellowshipOfTheRing).extracting(ageAndRace()).contains(tuple(33, HOBBIT),
                                                                  tuple(38, HOBBIT),
                                                                  tuple(1000, ELF));

Here's what ageAndRace() extractor looks like:

public class TolkienCharacterAgeAndRaceExtractor implements Extractor<TolkienCharacter, Tuple> {

   @Override
   public Tuple extract(TolkienCharacter input) {
      return new Tuple(input.age, input.getRace());
   }

   public static Extractor<TolkienCharacter, Tuple> ageAndRace() {
      return new TolkienCharacterAgeAndRaceExtractor();
   }
}

We can do more than extracting values, we can also flatten them, much like a functional flatMap:
Example:

// BasketBallPlayer.getTeamMates returns a List<BasketBallPlayer>
BasketBallPlayer noah =  ... // initialized with Derrick Rose and Pau Gasol as teamates
BasketBallPlayer james =  ... // initialized with Kevin Love and Kyrie Irving as teamates

// extract team mates and "flatten" them to a single BasketBallPlayer collection
assertThat(asList(noah, james)).flatExtracting(teammates()).contains(gasol, love, irving, rose);

// teammates() extractor
public class BasketBallTeammatesExtractor
       implements Extractor<BasketBallPlayer, List<BasketBallPlayer>> {

   @Override
   public List<BasketBallPlayer> extract(BasketBallPlayer player) {
      return player.getTeamMates();
   }

   public static Extractor<BasketBallPlayer, List<BasketBallPlayer>> teammates() {
      return new BasketBallTeammatesExtractor();
   }
}

Mateusz has published a nice article on this new feature.

This assertion verifies that the actual map contains only the given keys and nothing else, in any order.
Example:

Map<Ring, TolkienCharacter> ringBearers = ... // init with elves rings and the one ring

// assertion will pass
assertThat(ringBearers).containsOnlyKeys(nenya, narya, vilya, oneRing);

// assertion will fail because of two missing keys and an unexpected one (dwarfRing)
assertThat(ringBearers).containsOnlyKeys(oneRing, nenya, dwarfRing);

Thanks to Chris Arnott for this contribution.

This assertion verifies that the actual map has the same size as the given Map.
Example:

Map<Ring, TolkienCharacter> ringBearers = ... // init with elves rings and the one ring

// assertion will pass
assertThat(ringBearers).hasSameSizeAs(mapOf(entry(oneRing, frodo),
                                            entry(narya, gandalf),
                                            entry(nenya, galadriel),
                                            entry(vilya, elrond)));

Thanks to Adam Ruka for this contribution.

The shell script will convert mots of your TestNG assertions to AssertJ ones.
Usage:

# default to *Test.java if you don't provide a pattern
./convert-testng-assertions-to-assertj.sh "*IT.java"

Thanks to Alexandre Balhier for this contribution.

This assertion verifies that the actual String/CharSequence has the expected number of lines.
Example:

String multiLine = "First line\n" +
                   "Last line";
assertThat(multiLine).hasLineCount(2);

Thanks to Mariusz Smykula for this contribution.

This assertion verifies that the actual iterable contains only the elements of the given iterable and nothing else, in any order.
Example:

Iterable<Ring> rings = newArrayList(nenya, vilya);

// assertion will pass
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya));
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, nenya, vilya, vilya));

// assertion will fail as actual does not contain narya.
assertThat(rings).containsOnlyElementsOf(newLinkedList(nenya, vilya, narya));

// assertion will fail as actual contain nenya.
assertThat(rings).containsOnlyElementsOf(newLinkedList(vilya));

Thanks to Chris Arnott for this contribution.

This assertion verifies that the actual iterable contains only the elements of the given iterable and nothing else, in any order.
Example:

Iterable<Ring> elvesRings = newArrayList(vilya, nenya, narya);

// assertions will pass
assertThat(elvesRings).hasSameElementsAs(newArrayList(nenya, narya, vilya));
assertThat(elvesRings).hasSameElementsAs(newArrayList(nenya, narya, vilya, nenya));

// assertions will fail
assertThat(elvesRings).hasSameElementsAs(newArrayList(nenya, narya));
assertThat(elvesRings).hasSameElementsAs(newArrayList(nenya, narya, vilya, oneRing));

This assertion verifies that there is at least one element in the actual iterable or array satisfying the given condition.
Example:

List<BasketBallPlayer> bullsPlayers = newArrayList(noah, rose);

// potentialMvp is a Condition<BasketBallPlayer>
assertThat(bullsPlayers).haveAtLeastOne(potentialMvp);

Thanks to Adam Ruka for this contribution.

These assertions verifies the type of the Iterable/Array elements.
Example:

// hasOnlyElementsOfType check
List<Long> numbers = newArrayList(1L, 2L);
assertThat(numbers).hasOnlyElementsOfType(Number.class)
                   .hasOnlyElementsOfType(Long.class);

// hasAtLeastOneElementOfType check
assertThat(newArrayList("string", 1L)).hasAtLeastOneElementOfType(String.class);

AssertJ now provides basic assertions for Comparable types.
Example:

Rating goodRating = new Rating(8);
Rating badRating = new Rating(4);

// basic assertions available for all Comparable types.
assertThat(goodRating).isGreaterThan(badRating);
assertThat(goodRating).isGreaterThanOrEqualTo(badRating);
assertThat(badRating).isLessThan(goodRating);
assertThat(badRating).isLessThanOrEqualTo(goodRating);

public class Rating implements Comparable {

  private int note;

  public Rating(int note) {
    this.note = note;
  }

  @Override
  public int compareTo(Rating r) {
    return this.note - r.note;
  }
}

Thanks to dmwvr for this contribution.

You can use field by field element comparison for array/iterable assertions but before 1.7.0 it only worked for array/iterable specific assertions and not basic ones isEqualTo(), now the semantics are also applied for basic assertions.
Example:

TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);
TolkienCharacter sam = new TolkienCharacter("Sam", 38, HOBBIT);

// frodo and sam both are hobbits -> they are equals when comparing only race (worked before 1.7.0)
assertThat(newArrayList(frodo)).usingElementComparatorOnFields("race").contains(sam);

// Before 1.7.0, this basic assertion would not work as element comparison semantics
// were only honoured in IterableAssert/Array specific assertions, but now it works !
assertThat(newArrayList(frodo)).usingElementComparatorOnFields("race").isEqualTo(newArrayList(sam));

Release date : 2014-06-01

This is a minor release to fix an OSGI incompatibility discovered by Giuseppe Guarnieri (thanks !), we also expose List<String> linesOf(File file) directly in the Assertions entry point class.

Release date : 2014-03-15

Thanks to Mariusz Smykula, Michal Lipski, Kamil Szymanski, Fabien Meurisse, Adam Dąbrowski, Paweł Barszcz, Clément Cunin, Gregor Zeitlinger, William Delanoue, Jean Christophe Gay, Tomasz Bartczak, Michal Bareja and Michał Piotrkowski for their contributions.

Example:

File xFileWithExtension = writeFile("xFile.secret", "The Truth Is Out There");
assertThat(xFileWithExtension).hasParent("target")
                              .hasParent(new File("target"))
                              .hasExtension("secret")
                              .hasName("xFile.secret");

assertThat(new File("/")).hasNoParent();

Thanks to Jean Christophe Gay for this contribution.

AssertJ allows now to register several custom date formats and their use is thread safe.

Example :

// You can use date String representation with various default format:
// - yyyy-MM-dd
// - yyyy-MM-dd'T'HH:mm:ss,
// - yyyy-MM-dd'T'HH:mm:ss.SSS,
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18");
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18T00.00.00");

// But you can register on or several custom date format (this is thread safe):
Assertions.registerCustomDateFormat("dd/MM/yyyy");
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("18/12/2002");

// default date formats can still be used
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18");

Example:

// within : static import of org.assertj.core.api.Assertions.within
assertThat(8.1).isCloseTo(8.0, within(0.1));

Extracting feature is now able to read private fields, for example:

// trilogy is collection of Movie which has a duration private field.
assertThat(trilogy).extracting("duration").containsExactly("178 min", "179 min", "201 min");

// you can disable private field extraction
setAllowExtractingPrivateFields(false);

// now assertion fails with an IntrospectionError.
assertThat(trilogy).extracting("duration").containsExactly("178 min", "179 min", "201 min");

Thanks to Michal Bareja and Paweł Barszcz for this contribution.

Sometimes it is difficult to find differences from standard message, for example:

assertThat("µµµ").contains("μμμ");

But with hexadecimal representation the difference is clear:

assertThat("µµµ").inHexadecimal().contains("μμμ");

Error:

Expecting:
 <"['0x00B5', '0x00B5', '0x00B5']">
to contain:
 <"['0x03BC', '0x03BC', '0x03BC']">

Thanks to Mariusz Smykula for this huge contribution.

When using Iterable assertions, you can now compare expected elements with actual ones using field by field comparison instead of equals method.

Example:

TolkienCharacter frodo = new TolkienCharacter("Frodo", 33, HOBBIT);
TolkienCharacter sam = new TolkienCharacter("Sam", 38, HOBBIT);

// frodo and sam both are hobbits, so they are equals when comparing only race
assertThat(newArrayList(frodo)).usingElementComparatorOnFields("race").contains(sam); // OK

// ... but not when comparing both name and race
assertThat(newArrayList(frodo)).usingElementComparatorOnFields("name", "race").contains(sam); // FAIL

Thanks to Tomasz Bartczak and Adam Dąbrowski for this contribution.

In case of error the actual field values are displayed (before only the expected values were), example:

This assertion ...

assertThat(frodo).isEqualToComparingOnlyGivenFields(sam, "name", "race", "age");

... will fail with the following error:

Expecting values:
  <["Sam", 38]>
in fields:
  <["name", "age"]>
but were:
  <["Frodo", 33]>
in <Frodo 33 years old Hobbit>.
Comparison was performed on fields:
  <["name", "race", "age"]>

Thanks to Michal Lipski and Paweł Barszcz for this contribution.

Instead of using assertThat use then to start assertions, example:

@Test
public void host_dinner_party_where_nobody_dies() {
   //given
   Mansion mansion = new Mansion();

   //when
   mansion.hostPotentiallyMurderousDinnerParty();

   then(mansion.guests()).isEqualTo(6);
   then(mansion.kitchen()).isEqualTo("clean");
   then(mansion.library()).isEqualTo("messy");
   then(mansion.revolverAmmo()).isEqualTo(6);
   then(mansion.candlestick()).isEqualTo("bent");
   then(mansion.colonel()).isEqualTo("well kempt");
   then(mansion.professor()).isEqualTo("bloodied and disheveled");
}  

Thanks to Mariusz Smykula for this contribution.

To avoid having to call assertAll() at the end of your test methods, let JUnitSoftAssertions JUnit rule triggers automatically the assertions global verification :

@Rule
public JUnitSoftAssertions softly = new JUnitSoftAssertions();

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   // use SoftAssertions instead of direct assertThat methods
   softly.assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
   softly.assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
   softly.assertThat(mansion.library()).as("Library").isEqualTo("clean");
   softly.assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
   softly.assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
   softly.assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
   softly.assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
   // No call to softly.assertAll(), assertions global verification is done by JUnitSoftAssertions rule
}

This works only for JUnit, in TestNG however it does not seem possible to make the global verification in an @AfterMethod method because if it throws an exception, TestNG skips all subsequent tests.

Thanks to Gregor Zeitlinger for this contribution.

  • BDD assertions style. (Mariusz Smykula)
  • Soft assertions automatic global verification with JUnit rule. (Gregor Zeitlinger)
  • Standard Java, Binary, Unicode and Hexadecimal representation of objects. (Mariusz Smykula)
  • File assertions: hasExtension, hasName, hasParent and hasNoParent. (Jean Christophe Gay)
  • Allow several custom date formats for date assertions
  • Add isCloseTo assertion for float, double and BigDecimal
  • Extracting feature : allow to extract private fields. (Michal Bareja and Paweł Barszcz)
  • Field by field comparison is now supported on Iterable assertions. (Tomasz Bartczak and Adam Dąbrowski)
  • Add CharSequence hasSameSizeAs assertion that takes a CharSequence. (Kamil Szymanski)
  • Better error messages when comparing objects field by field. (Michal Lipski and Paweł Barszcz)
  • Various Javadoc API improvements
  • Better script to convert JUnit assertions to AssertJ ones. (William Delanoue)
  • Fix Dates.assertIsEqualWithPrecision bug. (Fabien Meurisse)
  • Fix test depending on locale. (Clément Cunin)

Release date : 2013-11-06

Thanks to William Delanoue, Jean Christophe Gay, Tomasz Bartczak and Michał Piotrkowski for their contributions.

Like extracting feature but instead of extracting properties/fields, it extracts the result of given method invocation on the elements of Iterable/Array under test and puts the results into a new Iterable/Array which becomes the object under test.
It allows you to test the results of method call on elements instead of testing the elements themselves, it's especially useful for classes that does not conform to Java Bean's getter specification (e.g toString() or String status() instead of String getStatus()).

Let's take an example to make things clearer :

// Build a array of WesterosHouse, a WesterosHouse has a method: public String sayTheWords()
List<WesterosHouse> greatHouses = new ArrayList<WesterosHouse>();
greatHouses.add(new WesterosHouse("Stark", "Winter is Coming"));
greatHouses.add(new WesterosHouse("Lannister", "Hear Me Roar!"));
greatHouses.add(new WesterosHouse("Greyjoy", "We Do Not Sow"));
greatHouses.add(new WesterosHouse("Baratheon", "Our is the Fury"));
greatHouses.add(new WesterosHouse("Martell", "Unbowed, Unbent, Unbroken"));
greatHouses.add(new WesterosHouse("Tyrell", "Growing Strong"));

// let's verify the words of great houses in Westeros:
assertThat(greatHouses).extractingResultOf("sayTheWords")
                       .contains("Winter is Comming", "We Do Not Sow", "Hear Me Roar")
                       .doesNotContain("Lannisters always pay their debts");

Thanks to Michał Piotrkowski for this contribution.

isEqualToIgnoring<Millis/Seconds/Minutes/Hours> assertions allow you to compare two dates ignoring time fields below given precision, for example if you ignore minutes then seconds and milliseconds will be ignored too.
Code example: compare two dates without minutes, seconds and milliseconds

Date date1 = parseDatetime("2003-04-26T13:01:35");
Date date2 = parseDatetime("2003-04-26T13:02:00");

// OK : all dates fields are the same if we leave minutes seconds and milliseconds fields
assertThat(date1).isEqualToIgnoringMinutes(date2);

// KO : fail as minute fields differ
assertThat(date1).isEqualToIgnoringSeconds(date2);  

Thanks to William Delanoue for this contribution.

With isInSame<Second/Minute/Hour>WindowAs> you can check that two dates are in the same time window with a true chronological comparison and not a field by field comparison like we do in isInSame<Second/Minute/Hour>As.
Let's see that on an example :

Date date1 = parseDatetimeWithMs("2003-04-26T13:01:02.999");
Date date2 = parseDatetimeWithMs("2003-04-26T13:01:03.000");

// OK : assertion succeeds as time difference is 1ms < 1s
assertThat(date1).isInSameSecondWindowAs(date2);

// KO : isInSameSecondAs assertion fails as seconds fields differ.
assertThat(date1).isInSameSecondAs(date2);

You can use date String representation with various format, AssertJ takes care of parsing String as Date:

// - yyyy-MM-dd
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18");
// - yyyy-MM-dd'T'HH:mm:ss
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18T00.00.00");
// - yyyy-MM-dd'T'HH:mm:ss.SSS
assertThat(theTwoTowers.getReleaseDate()).isEqualTo("2002-12-18T00.00.00.000");

Add containsOnly and containsExactly to Map assertions using the same semantics as the one in Iterable assertions:

import static org.assertj.core.api.Assertions.entry;

Map<String, TolkienCharacter> characters = new LinkedHashMap<String, TolkienCharacter>();
characters.put(frodo.getName(), frodo);
characters.put(galadriel.getName(), galadriel);
characters.put(gandalf.getName(), gandalf);
characters.put(sam.getName(), sam);

assertThat(characters).containsOnly(entry(sam.getName(), sam),
                                    entry(frodo.getName(), frodo),
                                    entry(gandalf.getName(), gandalf),
                                    entry(galadriel.getName(), galadriel));

assertThat(characters).containsExactly(entry(frodo.getName(), frodo),
                                       entry(galadriel.getName(), galadriel),
                                       entry(gandalf.getName(), gandalf),
                                       entry(sam.getName(), sam));
  • Extracting feature for method calls. (Mariusz Smykula)
  • Add isInSame<Second/Minute/Hour>WindowAs assertions
  • Add isEqualToIgnoring<Millis/Seconds/Minutes/Hours> assertions. (William Delanoue)
  • New Iterable assertion feature: extractingResultOf. (Michał Piotrkowski)
  • New Map assertions: containsExactly and containsOnly (already existed for iterables). (Jean Christophe Gay)
  • Various Javadoc API improvements (have a look at date assertions)
  • AbstractIterableAssert.containsOnlyOnce() should not require objects to implement Comparable. (Tomasz Bartczak)
  • hasSameSizeAs() was not working with primitive arrays

Release date : 2013-11-06

Thanks to Brian Laframboise, William Delanoue, Marcus Klimstra, Ted Young, Piotr Betkier, Marcin Mikosik and Jean Christophe Gay for their contributions.

String based XML assertions have been added, it allows you to compare a String representing an XML document with another one whatever how formatted the XML is. Let's see that with some examples :

String expectedXml = "<rings>\n" +
                     "  <bearer>\n" +
                     "    <name>Frodo</name>\n" +
                     "      <ring>\n" +
                     "        <name>one ring</name>\n" +
                     "        <createdBy>Sauron</createdBy>\n" +
                     "      </ring>\n" +
                     "  </bearer>\n" +
                     "</rings>";

// XML String don't need to be formatted, isXmlEqualTo is able to compare it with another xml String.
String oneLineXml = "<rings><bearer><name>Frodo</name>"
                  + "<ring><name>one ring</name><createdBy>Sauron</createdBy>"
                  + "</ring></bearer></rings>";

assertThat(oneLineXml).isXmlEqualTo(expectedXml);

Since AssertJ formats both actual and expected XML String the same way, it's easy to see what was different in case of error.

You can also easily compare your XML String to the content of an XML file, e.g:

assertThat(xmlString).isXmlEqualToContentOf(new File("expected.xml"));

Using soft assertions, AssertJ collects all assertion errors instead of stopping at the first one.
So, assuming something goes awry at your dinner party, when using "standard" assertions, this test ...

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
   assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
   assertThat(mansion.library()).as("Library").isEqualTo("clean");
   assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
   assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
   assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
   assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
}  

... will yield the less-than-ideal exception message :

org.junit.ComparisonFailure: [Living Guests] expected:<[7]> but was<[6]>

Using soft assertions you can collect all the failed assertions together like so:

@Test
public void host_dinner_party_where_nobody_dies() {
   Mansion mansion = new Mansion();
   mansion.hostPotentiallyMurderousDinnerParty();
   // use SoftAssertions instead of direct assertThat methods
   SoftAssertions softly = new SoftAssertions();
   softly.assertThat(mansion.guests()).as("Living Guests").isEqualTo(7);
   softly.assertThat(mansion.kitchen()).as("Kitchen").isEqualTo("clean");
   softly.assertThat(mansion.library()).as("Library").isEqualTo("clean");
   softly.assertThat(mansion.revolverAmmo()).as("Revolver Ammo").isEqualTo(6);
   softly.assertThat(mansion.candlestick()).as("Candlestick").isEqualTo("pristine");
   softly.assertThat(mansion.colonel()).as("Colonel").isEqualTo("well kempt");
   softly.assertThat(mansion.professor()).as("Professor").isEqualTo("well kempt");
   // Don't forget to call SoftAssertions global verification !
   softly.assertAll();
}

When the collected assertions are all asserted together they yield a more descriptive error message:

org.assertj.core.api.SoftAssertionError:
     The following 4 assertions failed:
     1) [Living Guests] expected:<[7]> but was:<[6]>
     2) [Library] expected:<'[clean]'> but was:<'[messy]'>
     3) [Candlestick] expected:<'[pristine]'> but was:<'[bent]'>
     4) [Professor] expected:<'[well kempt]'> but was:<'[bloodied and dishevelled]'>

Thanks to Brian Laframboise for this contribution.

  • isLenientEqualsToByIgnoringFields renamed to isEqualToIgnoringGivenFields
  • isLenientEqualsToByAcceptingFields renamed to isEqualToComparingOnlyGivenFields
  • isLenientEqualsToByIgnoringNullFields renamed to isEqualToIgnoringNullFields
  • isEqualsToByComparingFields renamed to isEqualToComparingFieldByField
  • XML String assertions
  • Soft assertions to gather all error messages instead of stopping at the first one. (Brian Laframboise)
  • New Iterable assertion : containsExactlyElementsOf. (Jean Christophe Gay)
  • New Iterable assertion : containsSubsequence. (Marcin Mikosik)
  • Assertion file template for IntelliJ. (Piotr Betkier)
  • Test description (i.e. as() method) now supports String.format (William Delanoue)
  • Added Javadoc for String assertions and cleaned up English in Contributing.md (Ted Young)
  • Properties of inner classes that are indirectly visible through an interface should be accessible (Marcus Klimstra)
  • Various Javadoc API improvements

Release date : 2013-06-30

Thanks to William Delanoue, Jean Christophe Gay, Ted M. Young and Mikhail Mazursky for their contributions.

The following assertions that were deprecated since the first version (and coming from Fest Assert) have been removed, we thought that they were very unclear:

  • areNotAtLeast, areNotAtMost, areNotExactly
  • haveNotAtLeast, haveNotAtMost, haveNotExactly

Class assertions have been added, let's see that with some examples:

assertThat(Magical.class).isAnnotation();
assertThat(Ring.class).isNotAnnotation()
                      .hasAnnotation(Magical.class);

assertThat(TolkienCharacter.class).isNotInterface();
assertThat(Person.class).isAssignableFrom(Employee.class);

// You can check Class fields with :
// - hasFields for public fields
assertThat(TolkienCharacter.class).hasFields("age");
// - hasDeclaredFields for all declared fields (whatever field's visibility)
assertThat(TolkienCharacter.class).hasDeclaredFields("name", "race");
  • Removed : areNotAtLeast, areNotAtMost, areNotExactly
  • Removed : haveNotAtLeast, haveNotAtMost, haveNotExactly
  • Introduce Class assertions (William Delanoue)
  • New Throwables assertions : hasCauseInstanceOf, hasCauseExactlyInstanceOf, hasRootCauseInstanceOf and hasRootCauseExactlyInstanceOf (Jean Christophe Gay)
  • Add containsExactly assertion for arrays (already existed for iterables) (Jean Christophe Gay)
  • Add containsOnlyOnce assertion for arrays and iterables (William Delanoue)
  • Provide a way to extend AssertJ existing assertions that does not break assertion chaining, see issue 9 (Mikhail Mazursky)
  • Make isNotEqualTo, isIn and isNotIn assertions more flexible by not using generics in "expected" parameter (Mikhail Mazursky)
  • Allow defining the extracted type of extracted values from array in extracting feature (William Delanoue)
  • assertDoesNotMatch() String assertion should not allow object to check to be null (Mikhail Mazursky)
  • Javadoc API improvements
  • Cleaned up English in README.md (Ted Young)
  • Fix IterableAssert.startsWith infinite loop for inifinite iterables

Release date : 2013-05-12

Thanks to William Delanoue and Mikhail Mazursky for their contributions.

The First improvement is related to map entries, often testing map entries looks like :

Map<String, String> address = ....
assertThat(address).includes(MapAssert.entry("zip", "43865"),
                             MapAssert.entry("lastName", "Frazier"),
                             MapAssert.entry("state", "IA"),
                             MapAssert.entry("city", "Culloden"));

We can simplify this by getting rid of the repeated MapAssert.entry calls:

assertThat(address).containsEntry("zip", "43865")
                   .containsEntry("lastName", "Frazier")
                   .containsEntry("state", "IA")
                   .containsEntry("city", "Culloden");

Same thing has been done with doesNotContainEntry.

The second improvement is to allow checking that a Map contains multiple keys at once, so instead of :

assertThat(elvesRingBearers).containsKey(nenya).containsKey(narya).containsKey(vilya);

you can now write :

assertThat(elvesRingBearers).containsKeys(nenya, narya, vilya);

Make isEqualTo, isSameAs and isNotSameAs assertions more flexible by not using generics in "expected" parameter.
It solves the following problem where an Employee class inherits from Person :

Employee bill = new Employee("Bill", 50, "micro$oft");
// OK
assertThat(bill).isEqualTo(bill);

// now let's view billou as a Person and not an Employee anymore
Person billou = bill;

// Before 1.2.0 version, the next line used led to a compile error as
// parameter expected type is Employee (although bill and billou are identical).
assertThat(bill).isEqualTo(billou);

The only drawback is less strong type checking but we think flexibility is more important that type checks.
Note that this is the beginning of making AssertJ more flexible, there is still work to be done in this area.

  • Introduce CharSequenceAssert to support StringBuffer, StringBuilder and all subtypes of CharSequence assertions (Mikhail Mazursky)
  • New Iterable assertion : doesNotContainAnyElementsOf(Iterable) (William Delanoue)
  • New Number assertions : isBetween and isStrictlyBetween (William Delanoue)
  • Code coverage improvements
  • Make isEqualTo, isSameAs and isNotSameAs assertions more flexible by not using generics in "expected" parameter (William Delanoue / Mikhail Mazursky)
  • IterableAssert.doesNotHaveDuplicates performance enhancement (~500x faster)
  • Improve Map assertions related to entries (William Delanoue)
  • Improve Map assertions when checking several keys presence (William Delanoue)
  • Deprecate methods that are useless to avoid misleading users (Mikhail Mazursky)
  • Javadoc API improvements (still a lot to do ...)
  • Fix containsSequence assertion that stopped after first partial match

Release date : 2013-04-15

With extracting you can extract values from an array/iterable elements and perform assertions on those extracted values.
It is similar to extractProperty feature but is easier to use (I think), it is also able to extract properties as well as public fields while extractProperty can only extract properties (as its name suggests).

Last but not least, you can extract several public fields and properties at once, the extracted values corresponding to the same element being grouped in a tuple.

Simple example showing how to check the names of TolkienCharacter elements in fellowshipOfTheRing list :

// "name" need to be either a property or a public field of TolkienCharacter class.
assertThat(fellowshipOfTheRing).extracting("name")
                               .contains("Boromir", "Gandalf", "Frodo", "Legolas")
                               .doesNotContain("Sauron", "Elrond");

Example showing how to check the name, age and race's name of each TolkienCharacter elements :
the extracted name, age and race's name values corresponding to the same element are grouped in a tuple, thus you need to use tuples for expected values.

// tuple comes from : import static org.assertj.core.api.Assertions.tuple;
assertThat(fellowshipOfTheRing).extracting("name", "age", "race.name")
                               .contains(tuple("Boromir", 37, "Man"),
                                         tuple("Sam", 38, "Hobbit"),
                                         tuple("Legolas", 1000, "Elf"));

This feature is a much more powerful version of onProperty that was introduced in Fest 1.4.

Error messages are now multiline to ease comparing the actual value to the expected one.

Here an example with a failing Date assertion :

// failing assertion !
assertThat(parse("2013-01-01")).isBefore(parse("2000-01-01"));

In assertj-core 1.0.0, it produces this error message :

expected:<2013-01-01T00:00:00> to be strictly before:<2000-01-01T00:00:00>

In assertj-core 1.1.0 the error message is now :

Expecting:
   <2013-01-01T00:00:00>
   to be strictly before:
   <2000-01-01T00:00:00>

Note that involved objects are aligned to the same column to ease comparing them.

  • Reintroduce onProperty feature but named it extracting
  • extracting() method is now able to extract fields
  • Allow extracting several fields or properties in iterable or array assertions
  • Assertions error messages are now multiline for better readability
  • Fix Problem with AbstractAssert.overridingErrorMessage(String newErrorMessage, Object[] args)
  • All contains assertions should not throw an exception if actual and values are empty

Release date : 2013-03-26

1.0.0 version is the first AssertJ release after the fork from FEST 2.0M10. These are the changes compared to FEST 2.0M10 :

  • Add StringAssert.containsSequence assertion
  • Make custom assertions easier to write
  • Varargs for StringAssert.contains() to avoid repeating contains several times
  • Add osgi metadata to MANIFEST
  • assertThat() should accept an Iterator