Introduzione ad Assert J.

Questo articolo fa parte di una serie: • Introduzione ad AssertJ (articolo corrente) • AssertJ per Guava

• Funzionalità Java 8 di AssertJ

• Asserzioni personalizzate con AssertJ

1. Panoramica

In questo articolo esploreremo AssertJ, una libreria open source guidata dalla comunità utilizzata per scrivere asserzioni fluide e ricche nei test Java.

Questo articolo si concentra sugli strumenti disponibili nel modulo AssertJ di base chiamato AssertJ-core .

2. Dipendenze di Maven

Per utilizzare AssertJ, è necessario includere la seguente sezione nel file pom.xml :

 org.assertj assertj-core 3.4.1 test  

Questa dipendenza copre solo le asserzioni Java di base. Se desideri utilizzare asserzioni avanzate, dovrai aggiungere moduli aggiuntivi separatamente.

Notare che per Java 7 e precedenti è necessario utilizzare AssertJ core versione 2.xx

Le ultime versioni possono essere trovate qui.

3. Introduzione

AssertJ fornisce una serie di classi e metodi di utilità che ci consentono di scrivere facilmente asserzioni fluide e belle per:

  • Java standard
  • Java 8
  • Guaiava
  • Joda Time
  • Neo4J e
  • Componenti dell'oscillazione

Un elenco dettagliato di tutti i moduli è disponibile sul sito web del progetto.

Cominciamo con alcuni esempi, direttamente dalla documentazione di AssertJ:

assertThat(frodo) .isNotEqualTo(sauron) .isIn(fellowshipOfTheRing); assertThat(frodo.getName()) .startsWith("Fro") .endsWith("do") .isEqualToIgnoringCase("frodo"); assertThat(fellowshipOfTheRing) .hasSize(9) .contains(frodo, sam) .doesNotContain(sauron);

Gli esempi precedenti sono solo la punta dell'iceberg, ma ci danno una panoramica di come potrebbe apparire la scrittura di asserzioni con questa libreria.

4. AssertJ in azione

In questa sezione ci concentreremo sulla configurazione di AssertJ e sull'esplorazione delle sue possibilità.

4.1. Iniziare

Con il jar della libreria su un classpath, abilitare le asserzioni è facile come aggiungere una singola importazione statica alla classe di test:

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

4.2. Scrittura di asserzioni

Per scrivere un'asserzione, devi sempre iniziare passando il tuo oggetto al metodo Assertions.assertThat () e poi seguire le asserzioni effettive.

È importante ricordare che, a differenza di altre librerie, il codice seguente in realtà non afferma ancora nulla e non fallirà mai un test:

assertThat(anyRefenceOrValue);

Se utilizzi le funzionalità di completamento del codice del tuo IDE, scrivere asserzioni di AssertJ diventa incredibilmente facile grazie ai suoi metodi molto descrittivi. Ecco come appare in IntelliJ IDEA 16:

Funzionalità di completamento del codice di IDE

Come puoi vedere, hai dozzine di metodi contestuali tra cui scegliere e quelli sono disponibili solo per il tipo String . Esploriamo in dettaglio alcune di questa API e guardiamo alcune affermazioni specifiche.

4.3. Asserzioni di oggetti

Gli oggetti possono essere confrontati in vari modi per determinare l'uguaglianza di due oggetti o per esaminare i campi di un oggetto.

Diamo un'occhiata a due modi in cui possiamo confrontare l'uguaglianza di due oggetti. Dati i seguenti due oggetti Dog fido e fidosClone :

public class Dog { private String name; private Float weight; // standard getters and setters } Dog fido = new Dog("Fido", 5.25); Dog fidosClone = new Dog("Fido", 5.25);

Possiamo confrontare l'uguaglianza con la seguente affermazione:

assertThat(fido).isEqualTo(fidosClone);

Questo fallirà poiché isEqualTo () confronta i riferimenti agli oggetti. Se invece vogliamo confrontare il loro contenuto, possiamo usare isEqualToComparingFieldByFieldRecursively () in questo modo:

assertThat(fido).isEqualToComparingFieldByFieldRecursively(fidosClone);

Fido e fidosClone sono uguali quando si esegue un campo ricorsivo per confronto di campi perché ogni campo di un oggetto viene confrontato con il campo nell'altro oggetto.

Esistono molti altri metodi di asserzione che forniscono modi diversi per confrontare e contrarre oggetti e per esaminare e affermare i loro campi. Per scoprirli tutti, fare riferimento alla documentazione ufficiale di AbstractObjectAssert .

4.4. Asserzioni booleane

Esistono alcuni metodi semplici per testare la verità:

  • è vero()
  • è falso()

Vediamoli in azione:

assertThat("".isEmpty()).isTrue();

4.5. Asserzioni iterabili / array

Per un Iterable o un Array esistono diversi modi per affermare che il loro contenuto esiste. Una delle asserzioni più comuni sarebbe quella di verificare se un Iterable o un Array contiene un dato elemento:

List list = Arrays.asList("1", "2", "3"); assertThat(list).contains("1");

o se una lista non è vuota:

assertThat(list).isNotEmpty();

o se una lista inizia con un dato carattere. Ad esempio "1":

assertThat(list).startsWith("1");

Tieni presente che se desideri creare più di un'asserzione per lo stesso oggetto, puoi unirle facilmente.

Di seguito è riportato un esempio di asserzione che controlla se un elenco fornito non è vuoto, contiene l'elemento "1", non contiene valori nulli e contiene una sequenza di elementi "2", "3":

assertThat(list) .isNotEmpty() .contains("1") .doesNotContainNull() .containsSequence("2", "3");

Of course many more possible assertions exist for those types. In order to discover them all, refer to the official AbstractIterableAssert documentation.

4.6. Character Assertions

Assertions for character types mostly involve comparisons and even checking if a given character is from a Unicode table.

Here is an example of an assertion that checks if a provided character is not ‘a', is in Unicode table, is greater than ‘b' and is lowercase:

assertThat(someCharacter) .isNotEqualTo('a') .inUnicode() .isGreaterThanOrEqualTo('b') .isLowerCase();

For a detailed list of all character types' assertions, see AbstractCharacterAssert documentation.

4.7. Class Assertions

Assertions for Class type are mostly about checking its fields, Class types, presence of annotations and class finality.

If you want to assert that class Runnable is an interface, you need to simply write:

assertThat(Runnable.class).isInterface();

or if you want to check if one class is assignable from the other:

assertThat(Exception.class).isAssignableFrom(NoSuchElementException.class);

All possible Class assertions can be viewed in the AbstractClassAssert documentation.

4.8. File Assertions

File assertions are all about checking if a given File instance exists, is a directory or a file, has certain content, is readable, or has given extension.

Here you can see an example of an assertion that checks if a given file exists, is file and not a directory, can be readable and writable:

 assertThat(someFile) .exists() .isFile() .canRead() .canWrite();

All possible Class assertions can be viewed in the AbstractFileAssert documentation.

4.9. Double/Float/Integer Assertions

Double/Float/Integer and Other Number Types

Numeric assertions are all about comparing numeric values within or without a given offset. For example, if you want to check if two values are equal according to a given precision we can do the following:

assertThat(5.1).isEqualTo(5, withPrecision(1d));

Notice that we are using already imported withPrecision(Double offset) helper method for generating Offset objects.

For more assertions, visit AbstractDoubleAssert documentation.

4.10. InputStream Assertions

There is only one InputStream-specific assertion available:

  • hasSameContentAs(InputStream expected)

and in action:

assertThat(given).hasSameContentAs(expected);

4.11. Map Assertions

Map assertions allow you to check if a map contains certain entry, set of entries, or keys/values separately.

And here you can see an example of an assertions that checks if a given map is not empty, contains numeric key “2”, does not contain numeric key “10” and contains entry: key: 2, value: “a”:

assertThat(map) .isNotEmpty() .containsKey(2) .doesNotContainKeys(10) .contains(entry(2, "a"));

For more assertions, see AbstractMapAssert documentation.

4.12. Throwable Assertions

Throwable assertions allow for example: inspecting exception's messages, stacktraces, cause checking or verifying if an exception has been thrown already.

Let's have a look at the example of an assertion that checks if a given exception was thrown and has a message ending with “c”:

assertThat(ex).hasNoCause().hasMessageEndingWith("c");

For more assertions, see AbstractThrowableAssert documentation.

5. Describing Assertions

In order to achieve even higher verbosity level, you can create dynamically generated custom descriptions for your assertions. The key to doing this is the as(String description, Object… args) method.

If you define your assertion like this:

assertThat(person.getAge()) .as("%s's age should be equal to 100", person.getName()) .isEqualTo(100);

this is what you will get when running tests:

[Alex's age should be equal to 100] expected: but was:

6. Java 8

AssertJ sfrutta appieno le funzionalità di programmazione funzionale di Java 8. Immergiamoci in un esempio e guardiamolo in azione. Per prima cosa vediamo come lo facciamo in Java 7:

assertThat(fellowshipOfTheRing) .filteredOn("race", HOBBIT) .containsOnly(sam, frodo, pippin, merry);

Qui stiamo filtrando una raccolta sulla razza Hobbit e in Java 8 possiamo fare qualcosa del genere:

assertThat(fellowshipOfTheRing) .filteredOn(character -> character.getRace().equals(HOBBIT)) .containsOnly(sam, frodo, pippin, merry);

Esploreremo le capacità Java8 di AssertJ in un prossimo articolo di questa serie. Gli esempi sopra sono stati presi dal sito web di AssertJ.

7. Conclusione

In questo articolo abbiamo esplorato brevemente le possibilità che AssertJ ci offre insieme alle affermazioni più popolari per i tipi Java principali.

L'implementazione di tutti gli esempi e frammenti di codice può essere trovata in un progetto GitHub.

Avanti » AssertJ per Guava