JUnit selalu membuat satu instance kelas pengujian untuk setiap metode @Test. Ini adalah keputusan desain mendasar untuk mempermudah penulisan tes tanpa efek samping. Pengujian yang baik tidak memiliki dependensi order-of-run (lihat FIRST ) dan membuat instance baru dari kelas pengujian dan variabel instance-nya untuk setiap pengujian sangat penting untuk mencapai hal ini. Beberapa framework pengujian menggunakan kembali instance kelas pengujian yang sama untuk semua pengujian, yang mengarah pada lebih banyak kemungkinan menciptakan efek samping secara tidak sengaja di antara pengujian.
Dan karena setiap metode pengujian memiliki instance sendiri, tidak masuk akal jika metode @ BeforeClass / @ AfterClass menjadi metode instance. Jika tidak, pada instance kelas pengujian manakah metode yang harus dipanggil? Jika memungkinkan untuk metode @ BeforeClass / @ AfterClass untuk mereferensikan variabel instans, maka hanya salah satu metode @Test yang akan memiliki akses ke variabel instans yang sama - sisanya akan memiliki variabel instans pada nilai defaultnya - dan @ Metode pengujian akan dipilih secara acak, karena urutan metode dalam file .class tidak ditentukan / compiler-dependent (IIRC, API refleksi Java mengembalikan metode dalam urutan yang sama seperti yang dideklarasikan dalam file .class, meskipun perilaku tersebut juga tidak ditentukan - Saya telah menulis perpustakaan untuk benar-benar menyortirnya berdasarkan nomor barisnya).
Jadi menegakkan metode tersebut menjadi statis adalah satu-satunya solusi yang masuk akal.
Berikut ini contohnya:
public class ExampleTest {
@BeforeClass
public static void beforeClass() {
System.out.println("beforeClass");
}
@AfterClass
public static void afterClass() {
System.out.println("afterClass");
}
@Before
public void before() {
System.out.println(this + "\tbefore");
}
@After
public void after() {
System.out.println(this + "\tafter");
}
@Test
public void test1() {
System.out.println(this + "\ttest1");
}
@Test
public void test2() {
System.out.println(this + "\ttest2");
}
@Test
public void test3() {
System.out.println(this + "\ttest3");
}
}
Yang mencetak:
beforeClass
ExampleTest@3358fd70 before
ExampleTest@3358fd70 test1
ExampleTest@3358fd70 after
ExampleTest@6293068a before
ExampleTest@6293068a test2
ExampleTest@6293068a after
ExampleTest@22928095 before
ExampleTest@22928095 test3
ExampleTest@22928095 after
afterClass
Seperti yang Anda lihat, setiap pengujian dijalankan dengan instance-nya sendiri. Apa yang dilakukan JUnit pada dasarnya sama dengan ini:
ExampleTest.beforeClass();
ExampleTest t1 = new ExampleTest();
t1.before();
t1.test1();
t1.after();
ExampleTest t2 = new ExampleTest();
t2.before();
t2.test2();
t2.after();
ExampleTest t3 = new ExampleTest();
t3.before();
t3.test3();
t3.after();
ExampleTest.afterClass();
Jawaban singkatnya adalah ini: tidak ada alasan yang tepat untuk itu menjadi statis.
Faktanya, membuatnya statis menyebabkan semua jenis masalah jika Anda menggunakan Junit untuk menjalankan tes integrasi DAO berbasis DBUnit. Persyaratan statis mengganggu injeksi dependensi, akses konteks aplikasi, penanganan resource, logging, dan apa pun yang bergantung pada "getClass".
sumber
@PostConstruct
untuk penyiapan dan@AfterClass
untuk meruntuhkan dan saya mengabaikan yang statis dari Junit sama sekali. Untuk tes DAO saya kemudian menulisTestCaseDataLoader
kelas saya sendiri yang saya panggil dari metode ini.@PostConstruct
dan@AfterClass
hanya berperilaku sama seperti@Before
dan@After
. Faktanya, metode Anda akan dipanggil untuk setiap metode pengujian dan tidak hanya sekali untuk seluruh kelas (seperti yang dinyatakan Esko Luontola dalam jawabannya, sebuah instance kelas dibuat untuk setiap metode pengujian). Saya tidak dapat melihat kegunaan solusi Anda jadi (kecuali jika saya melewatkan sesuatu)Dokumentasi JUnit tampaknya langka, tetapi saya akan menebak: mungkin JUnit membuat instance baru dari kelas pengujian Anda sebelum menjalankan setiap kasus pengujian, jadi satu-satunya cara agar status "fixture" Anda tetap ada di seluruh proses adalah membuatnya statis, yang dapat diterapkan dengan memastikan fixtureSetup Anda (metode @BeforeClass) statis.
sumber
Meskipun ini tidak akan menjawab pertanyaan awal. Ini akan menjawab tindak lanjut yang jelas. Cara membuat aturan yang berfungsi sebelum dan sesudah kelas serta sebelum dan sesudah pengujian.
Untuk mencapai itu, Anda dapat menggunakan pola ini:
Pada sebelum (Kelas) JPAConnection membuat koneksi sekali setelah (Kelas) menutupnya.
getEntityManger
mengembalikan kelas dalamJPAConnection
yang mengimplementasikan EntityManager jpa dan dapat mengakses koneksi di dalamjpaConnection
. Pada sebelum (tes) itu memulai transaksi setelah (tes) itu berputar kembali.Ini tidak aman untuk thread tetapi dapat dibuat sedemikian rupa.
Kode yang dipilih dari
JPAConnection.class
sumber
Tampaknya JUnit membuat instance baru dari kelas pengujian untuk setiap metode pengujian. Coba kode ini
Outputnya 0 0 0
Ini berarti bahwa jika metode @BeforeClass tidak statis maka itu harus dijalankan sebelum setiap metode pengujian dan tidak akan ada cara untuk membedakan antara semantik @Before dan @BeforeClass
sumber
ada dua jenis anotasi:
jadi @BeforeClass harus dideklarasikan statis karena dipanggil sekali. Anda juga harus mempertimbangkan bahwa menjadi statis adalah satu-satunya cara untuk memastikan propagasi "status" yang tepat di antara pengujian (model JUnit memberlakukan satu instance pengujian per @Test) dan, karena di Java hanya metode statis yang dapat mengakses data statis ... @BeforeClass dan @ AfterClass hanya dapat diterapkan ke metode statis.
Tes contoh ini harus menjelaskan penggunaan @BeforeClass vs @Before:
keluaran:
sumber
Sesuai JUnit 5, tampaknya filosofi untuk secara ketat membuat instance baru per metode pengujian agak longgar. Mereka telah menambahkan anotasi yang akan membuat instance kelas pengujian hanya sekali. Karenanya, anotasi ini juga memungkinkan metode yang dianotasi dengan @ BeforeAll / @ AfterAll (pengganti ke @ BeforeClass / @ AfterClass) menjadi non-statis. Jadi, kelas uji coba seperti ini:
akan mencetak:
Jadi, Anda sebenarnya dapat membuat instance objek satu kali per kelas pengujian. Tentu saja, hal ini menjadi tanggung jawab Anda sendiri untuk menghindari mutasi objek yang dibuat dengan cara ini.
sumber
Untuk mengatasi masalah ini, ubah saja metodenya
untuk
dan semua yang didefinisikan dalam metode ini untuk
static
.sumber