Tips and tricks - alexruiz/fest-assert-2.x GitHub Wiki

(to main page)

Here's some tips we are using to make writing tests easier and more elegant.
Please share your tips with us, this page can be edited by everybody !

Tips


How to configure your IDE to directly get asserThat with code completion ?

The idea is to start typing asser and let code completion suggest you asserThat from Fest (and not the one from Hamcrest !).

  1. In Eclipse, go to : preferences > Java > Editor > Content assist > Favorites > New Type
  2. Enter : org.fest.assertions.api.Assertions
  3. You should see : org.fest.assertions.api.Assertions.* in a the list.

For Idea, I don't know, but I'm sure it's possible ;-)


Exception assertions best practices

The goal here is to assert that an exception has been thrown and that exception is the one expected.

  1. Put the code to should throw in a try-catch.
  2. Call a fail method immediately after the code that should throw an exception, so that if exception is not thrown, the test will fail.
  3. Make assertions on the caught exception

Note that fail method can statically imported from Assertions class

Example taken from FailUsageExamples in fest-example project :

import static org.fest.assertions.api.Assertions.assertThat;
import static org.fest.assertions.api.Assertions.fail;
import static org.fest.assertions.api.Assertions.failBecauseExceptionWasNotThrown;

...

assertThat(fellowshipOfTheRing).hasSize(9);

// here's the typical pattern to use Fail :
try {
  fellowshipOfTheRing.get(9); // argggl !
  // we should not arrive here => use fail to expresses that
  // if IndexOutOfBoundsException was not thrown, test would fail the specified message 
  fail("IndexOutOfBoundsException expected because fellowshipOfTheRing has only 9 elements");
} catch (IndexOutOfBoundsException e) {
  assertThat(e).hasMessage("Index: 9, Size: 9");
}

// Warning : don't catch Throwable in catch clause as it would also catch AssertionError thrown by fail method

// another way to do the same thing 
try {
  fellowshipOfTheRing.get(9); // argggl !
  // if IndexOutOfBoundsException was not thrown, test would fail with message : 
  // "Expected IndexOutOfBoundsException to be thrown"
  failBecauseExceptionWasNotThrown(IndexOutOfBoundsException.class);
} catch (IndexOutOfBoundsException e) {
  assertThat(e).hasMessage("Index: 9, Size: 9");
}

Assertions on extracted properties of an iterable/array

When you are persisting objects, your persistent objects usually have ids. When writing a DAO/repository tests querying datastore, you only want to check that the returned objects have the expected ids.

You would write something like :

List<TolkienCharacter> fellowshipOfTheRing = tolkienDao.findHeroes();  // frodo, sam, aragorn ... 

// extract the ids ...
List<Long> ids = new ArrayList<Long>();
for (TolkienCharacter tolkienCharacter : fellowshipOfTheRing) {
  ids.add(tolkienCharacter.hashCode());
}
// ... and finally assert something
assertThat(ids).contains(1L, 2L, 3L);

It is too much work to have to extract ids, so we are taking care of that for you of extracting the properties, see below :

// no more manual ids extraction !
assertThat(extractProperty("id").from(fellowshipOfTheRing)).contains(1L, 2L, 3L);
// to be more type safe, you can define the property type with extractProperty second parameter
assertThat(extractProperty("id", Long.class).from(fellowshipOfTheRing)).contains(1L, 2L, 3L);

You can even extract nested properties using the dot notation, for example :

assertThat(extractProperty("race.name").from(fellowshipOfTheRing)).contains("Hobbit", "Elf")

See more examples in test method iterable_assertions_on_extracted_property_values_example in IterableAssertionsExamples.java from fest-examples project.


Using a custom comparison strategy in assertions

Sometime you want to compare objects with another strategy than equals method, this is possible in Fest thanks to two methods :

  • usingComparator(Comparator) : concerns object under assertion
  • usingElementComparator(Comparator) : concerns elements of iterable/array under assertion

usingComparator(Comparator) example :

// frodo and sam are instances of Character with Hobbit race (obviously :), they are not equal ... 
assertThat(frodo).isNotEqualTo(sam); 
// ... but if we compare race only, they are (raceComparator implements Comparator<Character>) 
assertThat(frodo).usingComparator(raceComparator).isEqualTo(sam); 

usingElementComparator(Comparator) example :

// standard comparison : the fellowshipOfTheRing includes Gandalf but not Sauron (believe me) ...
assertThat(fellowshipOfTheRing).contains(gandalf).doesNotContain(sauron);

// ... but if we compare race only, Sauron is in fellowshipOfTheRing (he's a Maia like Gandalf)
assertThat(fellowshipOfTheRing).usingElementComparator(raceComparator).contains(sauron);

Filtering a group of objects before making assertions

Filtering can be done on arrays or iterables, filters criteria are expressed by :

  • a Condition
  • some operation on property of array/iterable elements

Let's see both options on some examples taken from FilterExamples from fest-examples project.

Filtering on extracted properties values

// with(property).equalsTo(someValue) works by instrospection on specified property
assertThat(filter(fellowshipOfTheRing).with("race").equalsTo(HOBBIT).get())
          .containsOnly(sam, frodo, pippin, merry);
// same thing - shorter way
assertThat(filter(fellowshipOfTheRing).with("race", HOBBIT).get())
          .containsOnly(sam, frodo, pippin, merry);

// nested property are supported
assertThat(filter(fellowshipOfTheRing).with("race.name").equalsTo("Man").get())
          .containsOnly(aragorn, boromir);

// you can apply different comparison
assertThat(filter(fellowshipOfTheRing).with("race").notIn(HOBBIT, MAN).get())
          .containsOnly(gandalf, gimli, legolas);
assertThat(filter(fellowshipOfTheRing).with("race").in(MAIA, MAN).get())
          .containsOnly(gandalf, boromir, aragorn);
assertThat(filter(fellowshipOfTheRing).with("race").notEqualsTo(HOBBIT).get())
          .contains(gandalf, boromir, gimli,aragorn, legolas);

// you can chain multiple filter criteria 
assertThat(filter(fellowshipOfTheRing).with("race").equalsTo(MAN)
                                      .and("name").notEqualsTo("Boromir").get())
                                      .contains(aragorn);
}

Filtering with Condition

Two methods are available : being(Condition) and having(Condition), they do the same job - pick the one that makes your code the more readable !

// having(condition) example
Condition<Player> mvpStats= new Condition<Player>() {
  @Override
  public boolean matches(Player player) {
    return player.pointsPerGame() > 20 && (player.assistsPerGame() >= 8 || player.reboundsPerGame() >= 8);
  }
};
assertThat(filter(players).having(mvpStats).get()).containsOnly(rose, james);

// being(condition) example : same condition can be applied but is renamed to be more readable
Condition<Player> potentialMvp= mvpStats;
assertThat(filter(players).being(potentialMvp).get()).containsOnly(rose, james);

Using String assertions on the content of a file

File assertions are rather poor when it comes to check the file content, so we had the idea to reuse Fest String assertions on the content of a file.

See the example below :

File xFile = writeFile("xFile", "The Truth Is Out There");
// classic File assertions
assertThat(xFile).exists().isFile().isRelative(); 
// String assertions on the file content : contentOf() comes from Assertions.contentOf static import
assertThat(contentOf(xFile)).startsWith("The Truth").contains("Is Out").endsWith("There");

Note that it is meant to be used with small files since the whole content is loaded in memory.

⚠️ **GitHub.com Fallback** ⚠️