Puoi aggiungere un messaggio personalizzato ad AssertJ assertThat?


93

Abbiamo una suite di test che utilizza principalmente le asserzioni JUnit con i matcher Hamcrest. Uno del nostro team ha iniziato a sperimentare con AssertJ e ha impressionato le persone con la sua sintassi, flessibilità e dichiaratività. C'è una funzionalità fornita da JUnit per la quale non riesco a trovare un equivalente in AssertJ: l'aggiunta di un messaggio di errore di asserzione personalizzato.

Spesso confrontiamo oggetti che non sono fatti per la leggibilità umana e avranno ID o UUID apparentemente casuali ed è impossibile dire cosa dovrebbero essere dai dati che contengono. Questa è una situazione inevitabile per la nostra base di codice, purtroppo, poiché parte dello scopo che soddisfa è mappare i dati tra altri servizi senza necessariamente capire di cosa si tratta.

In JUnit, il assertThatmetodo fornisce una versione con un String reasonparametro prima del Matcher<T>param. Ciò rende banale aggiungere una breve stringa di debug per far luce sul problema, ad esempio cosa dovrebbe significare il confronto per un essere umano.

AssertJ, d'altra parte, fornisce un miliardo di metodi genericistatic assertThat diversi che restituiscono una qualche forma di interfaccia Assert o una delle sue numerose classi di implementazione. Questa interfaccia non fornisce un modo standard per impostare un messaggio personalizzato da includere negli errori.

C'è un modo per ottenere questa funzionalità dall'API di AssertJ o da una delle sue estensioni senza dover creare una classe di asserzione personalizzata per ogni tipo di asserzione a cui vogliamo aggiungere messaggi?

Risposte:


139

E in modo classico, ho trovato quello che stavo cercando pochi istanti dopo aver pubblicato la domanda. Si spera che questo renderà più facile la ricerca per la prossima persona senza dover prima sapere come si chiama. Il metodo magico è il nome ingannevolmente abbreviato as, che fa parte di un'altra interfaccia che AbstractAssertimplementa: Descriptable , non l'interfaccia Assert di base.

public S as(String description, Object... args)

Imposta la descrizione di questo oggetto che supporta la String.format(String, Object...)sintassi.
Esempio :

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description with as() method or describedAs(), it supports String format args
  assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("[check Frodo's age] expected:<[33]> but was:<[50]>");
}

Dove quella stringa tra virgolette nel blocco catch hasMessageè ciò che appare nel log di output dello unit test se l'asserzione fallisce.


L'ho trovato notando l' failWithMessagehelper nella pagina di asserzione personalizzata collegata alla domanda. Il JavaDoc per quel metodo indica che è protetto, quindi non può essere utilizzato dai chiamanti per impostare un messaggio personalizzato. Tuttavia menziona l' ashelper:

Inoltre, questo metodo rispetta qualsiasi descrizione impostata con as(String, Object...)o sovrascriva il messaggio di errore definito dall'utente con overridingErrorMessage(String, Object...).

... e l' helper overridingErrorMessage , che sostituisce completamente il expected: ... but was:...messaggio AssertJ standard con la nuova stringa fornita.

La homepage di AssertJ non menziona nessuno dei due helper fino alla pagina delle caratteristiche salienti, che mostra esempi asdell'helper nella sezione Soft Assertions , ma non descrive direttamente cosa fa.


25

Per aggiungere un'altra opzione alla risposta di Patrick M:

Invece di usare Descriptable.as, puoi anche usare AbstractAssert.withFailMessage():

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description via withFailMessage(), supports String format args
  assertThat(frodo.getAge()).
    withFailMessage("Frodo's age is wrong: %s years, difference %s years",
      frodo.getAge(), frodo.getAge()-33).
    isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("Frodo's age is wrong: 50 years, difference 17 years");
}

La differenza rispetto all'uso Descriptable.asè che ti dà il controllo completo sul messaggio personalizzato - non c'è "previsto" e "ma era".

Ciò è utile quando i valori effettivi testati non sono utili per la presentazione: questo metodo consente di mostrare altri valori, possibilmente calcolati, o nessuno.


Nota che, proprio come Descriptable.as, devi chiamare withFailMessage() prima di qualsiasi asserzione effettiva, altrimenti non funzionerà, poiché l'asserzione verrà attivata per prima. Questo è notato nel Javadoc.


4
"devi chiamare withFailMessage () prima di qualsiasi affermazione effettiva" grazie, questo mi ha fatto scattare. L'ordine di chiamare withFailMessagemateria; Mi piace AssertJ, ma fa schifo.
Abhijit Sarkar


0

Usa il as()metodo integrato in AssertJ. Per esempio:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.