Bisakah Anda menambahkan pesan khusus ke AssertJ assertThat?

90

Kami memiliki rangkaian pengujian yang utamanya menggunakan pernyataan JUnit dengan pencocok Hamcrest. Salah satu tim kami mulai bereksperimen dengan AssertJ dan membuat orang terkesan dengan sintaks, fleksibilitas, dan deklaratifnya. Ada satu fitur yang disediakan JUnit yang tidak dapat saya temukan padanannya di AssertJ: menambahkan pesan kegagalan pernyataan kustom.

Kami sering membandingkan objek yang tidak dibuat untuk dibaca manusia dan akan memiliki ID atau UUID yang tampak acak dan tidak mungkin untuk membedakan objek tersebut dengan data yang dikandungnya. Ini adalah situasi yang tidak dapat dihindari untuk basis kode kami, sayangnya, karena bagian dari tujuan yang dipenuhi adalah memetakan data antara layanan lain tanpa harus memahami apa itu.

Di JUnit, assertThatmetode ini menyediakan versi dengan String reasonparameter sebelum Matcher<T>param. Ini membuatnya mudah untuk menambahkan string debug pendek yang menjelaskan masalah, seperti apa arti perbandingan itu bagi manusia.

AssertJ, di sisi lain, menyediakan jillion berbeda genericizedstatic assertThat metode yang mengembalikan beberapa bentuk antarmuka Tegaskan atau salah satu dari banyak kelas pelaksanaannya. Antarmuka ini tidak menyediakan cara standar untuk menyetel pesan khusus untuk disertakan dengan kegagalan.

Apakah ada cara untuk mendapatkan fungsionalitas ini dari AssertJ API atau salah satu ekstensinya tanpa harus membuat kelas assert kustom untuk setiap jenis assert yang ingin kita tambahkan pesan?

Patrick M
sumber

Jawaban:

137

Dan dengan gaya klasik, saya menemukan apa yang saya cari beberapa saat setelah memposting pertanyaan. Mudah-mudahan hal ini akan memudahkan orang berikutnya untuk menemukannya tanpa harus tahu dulu apa namanya. Metode ajaib adalah nama pendek yang menipu as, yang merupakan bagian dari antarmuka lain yang AbstractAssertmengimplementasikan: Dapat dideskripsikan , bukan antarmuka Assert dasar.

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

Menetapkan deskripsi objek ini yang mendukung String.format(String, Object...)sintaks.
Contoh:

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]>");
}

Di mana string yang dikutip di blok catch hasMessageadalah apa yang muncul di log output pengujian unit Anda jika pernyataan gagal.


Saya menemukan ini dengan memperhatikan failWithMessagehelper di halaman pernyataan kustom yang ditautkan dalam pertanyaan. The javadoc untuk metode yang menunjukkan bahwa itu dilindungi, sehingga tidak dapat digunakan oleh penelepon untuk mengatur pesan khusus. Namun itu menyebutkan ashelper:

Selain itu, metode ini menghormati setiap kumpulan deskripsi dengan as(String, Object...)atau pesan kesalahan yang diganti yang ditentukan oleh pengguna dengan overridingErrorMessage(String, Object...).

... dan helper overridingErrorMessage , yang sepenuhnya menggantikan expected: ... but was:...pesan AssertJ standar dengan string baru yang disediakan.

Beranda AssertJ tidak menyebutkan helper mana pun hingga halaman sorotan fitur, yang menunjukkan contoh ashelper di bagian Soft Assertions , tetapi tidak secara langsung menjelaskan apa yang dilakukannya.

Patrick M
sumber
23

Untuk menambahkan opsi lain ke jawaban Patrick M:

Selain menggunakan Descriptable.as, Anda juga dapat menggunakan 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");
}

Perbedaan menggunakan Descriptable.asadalah memberikan Anda kendali penuh atas pesan khusus - tidak ada "yang diharapkan" dan "tetapi dulu".

Ini berguna jika nilai sebenarnya yang sedang diuji tidak berguna untuk presentasi - metode ini memungkinkan Anda untuk menampilkan nilai lain yang mungkin dihitung, atau tidak sama sekali.


Perhatikan bahwa, sama seperti Descriptable.as, Anda harus memanggil withFailMessage() sebelum pernyataan aktual - jika tidak, ini tidak akan berfungsi, karena pernyataan akan diaktifkan terlebih dahulu. Ini dicatat di Javadoc.

sleske
sumber
3
"Anda harus memanggil withFailMessage () sebelum pernyataan sebenarnya" terima kasih, ini membuat saya tersandung. Urutan panggilan withFailMessagemateri; Saya suka AssertJ, tapi ini menyebalkan.
Abhijit Sarkar
0

Gunakan as()metode inbuilt di AssertJ. Sebagai contoh:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
Testilla
sumber