Saya memiliki Suite Tes Integrasi. Saya memiliki IntegrationTestBase
kelas untuk memperpanjang semua tes saya. Kelas dasar ini memiliki metode @Before
( public void setUp()
) dan @After
( public void tearDown()
) untuk membangun koneksi API dan DB. Apa yang saya lakukan hanyalah mengganti kedua metode di setiap testcase dan menelepon super.setUp()
dan super.tearDown()
. Namun ini dapat menyebabkan masalah jika seseorang lupa untuk memanggil super atau menempatkan mereka di tempat yang salah dan pengecualian dilemparkan dan mereka lupa memanggil super pada akhirnya atau sesuatu.
Yang ingin saya lakukan adalah membuat setUp
dan tearDown
metode pada kelas dasar final
dan kemudian hanya menambahkan metode @Before
dan penjelasan kita sendiri @After
. Melakukan beberapa tes awal tampaknya selalu memanggil dalam urutan ini:
Base @Before
Test @Before
Test
Test @After
Base @After
tapi saya hanya sedikit khawatir bahwa pesanan tidak dijamin dan itu bisa menyebabkan masalah. Saya melihat sekeliling dan belum melihat apa-apa tentang masalah ini. Adakah yang tahu kalau saya bisa melakukan itu dan tidak ada masalah?
Kode:
public class IntegrationTestBase {
@Before
public final void setUp() { *always called 1st?* }
@After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
@Before
public final void before() { *always called 2nd?* }
@Test
public void test() { *always called 3rd?* }
@After
public final void after() { *always called 4th?* }
}
sumber
MyTest
hilang ituextends
?Jawaban:
Ya, perilaku ini dijamin:
@Before
:@After
:sumber
@Before
metode tidak dijamin. Jika ada 10@Before
metode, masing-masing dapat dieksekusi dalam urutan apa pun; sebelum metode lainnya.@Before
dan@After
metode dijalankan sebelum setiap metode kelas lainnya (sekali per metode), atau tepat sebelum dan setelah seluruh rangkaian metode kelas (satu kali per kelas)?junit-4.12
.Satu gotcha potensial yang telah menggigit saya sebelumnya:
Saya ingin memiliki paling banyak satu
@Before
metode di setiap kelas tes, karena urutan menjalankan@Before
metode yang ditentukan dalam kelas tidak dijamin. Biasanya, saya akan memanggil metode seperti itusetUpTest()
.Tetapi, meskipun
@Before
didokumentasikan sebagaiThe @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, ini hanya berlaku jika setiap metode yang ditandai dengan@Before
memiliki nama unik dalam hirarki kelas.Sebagai contoh, saya memiliki yang berikut ini:
Saya berharap
AbstractFooTest.setUpTest()
untuk berlari sebelumnyaFooTest.setUpTest()
, tetapi hanyaFooTest.setupTest()
dieksekusi.AbstractFooTest.setUpTest()
tidak dipanggil sama sekali.Kode harus dimodifikasi sebagai berikut agar berfungsi:
sumber
@Before
/@After
metode di kelas dasarfinal
, sehingga kompiler akan mengeluh jika Anda (secara tidak sengaja) mencoba menimpa mereka di subkelas.@Before
metode yang ditandai akan diabaikan jika subkelas juga memiliki@Before
metode.Saya pikir berdasarkan pada dokumentasi
@Before
dan@After
kesimpulan yang tepat adalah memberikan metode nama yang unik. Saya menggunakan pola berikut dalam pengujian saya:dan
berikan sebagai hasilnya
Keuntungan dari pendekatan ini: Pengguna kelas AbstractBaseTest tidak dapat mengganti metode setUp / tearDown secara tidak sengaja. Jika mereka mau, mereka perlu tahu nama persisnya dan bisa melakukannya.
(Kecil) Kerugian dari pendekatan ini: Pengguna tidak dapat melihat bahwa ada hal-hal yang terjadi sebelum atau setelah setUp / tearDown mereka. Mereka perlu tahu bahwa hal-hal ini disediakan oleh kelas abstrak. Tapi saya berasumsi itulah alasan mengapa mereka menggunakan kelas abstrak
sumber
Jika Anda membalikkan keadaan, Anda bisa mendeklarasikan abstrak kelas dasar Anda, dan memiliki keturunan yang menyatakan metode setUp dan tearDown (tanpa anotasi) yang dipanggil dalam metode setUp and tearDown kelas dasar '.
sumber
Anda dapat menggunakan
@BeforeClass
anotasi untuk memastikan yangsetup()
selalu disebut pertama. Demikian pula, Anda dapat menggunakan@AfterClass
anotasi untuk memastikan yangtearDown()
selalu disebut terakhir.Ini biasanya tidak disarankan, tetapi didukung .
Ini bukan apa yang Anda inginkan - tetapi pada dasarnya itu akan membuat koneksi DB Anda terbuka sepanjang waktu tes Anda berjalan, dan kemudian tutup sekali dan untuk semua di akhir.
sumber
setupDB()
dancloseDB()
dan menandai mereka dengan@BeforeClass
dan@AfterClass
dan mengganti / sebelum Anda setelah metode dengansetup()
dantearDown()
@BeforeClass
dan@AfterClass
harus statis. Bagaimana dengan kasus ini, ketika kita ingin menggunakan variabel instan di dalam metode ini?@BeforeClass
dengan Powermock: ini hanya berfungsi untuk percobaan pertama. Lihat masalah ini: github.com/powermock/powermock/issues/398Ini bukan jawaban untuk pertanyaan tagline, tetapi ini adalah jawaban untuk masalah yang disebutkan dalam tubuh pertanyaan. Alih-alih menggunakan @Before atau @After, lihatlah menggunakan @ org.junit.Rule karena itu memberi Anda lebih banyak fleksibilitas. ExternalResource (per 4.7) adalah aturan yang Anda akan paling tertarik jika Anda mengelola koneksi. Juga, Jika Anda ingin jaminan pelaksanaan aturan Anda gunakan RuleChain (per 4.10). Saya percaya semua ini tersedia saat pertanyaan ini diajukan. Contoh kode di bawah ini disalin dari javadocs ExternalResource.
sumber