Saya menyiapkan kelas dengan beberapa pengujian dan daripada menggunakan, @Before
saya ingin memiliki metode penyiapan yang hanya dijalankan sekali sebelum semua pengujian. Apakah itu mungkin dengan Junit 4.8?
Saya menyiapkan kelas dengan beberapa pengujian dan daripada menggunakan, @Before
saya ingin memiliki metode penyiapan yang hanya dijalankan sekali sebelum semua pengujian. Apakah itu mungkin dengan Junit 4.8?
Jawaban:
Meskipun saya setuju dengan @assylias bahwa menggunakan @BeforeClass
adalah solusi klasik tidak selalu nyaman. Metode yang dianotasi @BeforeClass
harus statis. Sangat merepotkan untuk beberapa tes yang membutuhkan contoh kasus uji. Misalnya pengujian berbasis Spring yang digunakan @Autowired
untuk bekerja dengan layanan yang ditentukan dalam konteks pegas.
Dalam hal ini saya pribadi menggunakan setUp()
metode biasa yang dianotasi dengan @Before
anotasi dan mengelola bendera custom static
(!) Saya boolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
metode dalam superclass - telah memposting jawaban di bawah ini mencoba untuk menyelesaikan ini.
Anda dapat menggunakan ini BeforeClass
penjelasan :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
selain panggilan getClass () Anda? Ini adalah Java yang sebenarnya: String.class.getName()
.
JUnit 5 sekarang memiliki anotasi @BeforeAll:
Menunjukkan bahwa metode yang dianotasi harus dijalankan sebelum semua metode @Test di kelas atau hierarki kelas saat ini; analog dengan @BeforeClass milik JUnit 4. Metode seperti itu harus statis.
Anotasi siklus hidup JUnit 5 tampaknya akhirnya benar! Anda dapat menebak anotasi mana yang tersedia tanpa perlu melihat (mis. @BeforeEach @AfterAll)
@BeforeClass
, itu perlu static
. Solusi IMO @ AlexR lebih bagus.
Saat setUp()
berada di superclass dari kelas tes (misalnya di AbstractTestBase
bawah), jawaban yang diterima dapat dimodifikasi sebagai berikut:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
Ini seharusnya bekerja untuk satu setUp()
metode non-statis tetapi saya tidak dapat menghasilkan yang setara tearDown()
tanpa tersesat ke dunia refleksi yang kompleks ... Bounty menunjuk kepada siapa saja yang bisa!
Sunting: Saya baru tahu saat men-debug bahwa kelas tersebut dibuat sebelum setiap tes juga. Saya kira anotasi @BeforeClass adalah yang terbaik di sini.
Anda juga dapat menyiapkan konstruktor, bagaimanapun juga, kelas pengujian adalah kelas. Saya tidak yakin apakah ini praktik yang buruk karena hampir semua metode lain diberi anotasi, tetapi berhasil. Anda bisa membuat konstruktor seperti itu:
public UT () {
// initialize once here
}
@Test
// Some test here...
Ctor akan dipanggil sebelum pengujian karena tidak statis.
Coba solusi ini: https://stackoverflow.com/a/46274919/907576 :
dengan @BeforeAllMethods
/ @AfterAllMethods
annotation Anda dapat menjalankan metode apa pun di kelas Test dalam konteks instance, di mana semua nilai yang dimasukkan tersedia.
Solusi kotor saya adalah:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
@Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
Saya menggunakannya sebagai basis dasar untuk semua testCases saya.
Jika Anda tidak ingin memaksakan deklarasi variabel yang disetel dan diperiksa pada setiap subtes, maka menambahkan ini ke SuperTest bisa dilakukan:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
Saya memecahkan masalah ini seperti ini:
Tambahkan ke kelas abstrak Basis Anda (maksud saya kelas abstrak tempat Anda menginisialisasi driver dalam metode setUpDriver () ) bagian kode ini:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
Dan sekarang, jika kelas pengujian Anda akan diperluas dari kelas abstrak Dasar -> metode setUpDriver () akan dijalankan sebelum @Test pertama hanya SATU kali per proses.
Gunakan metode @PostConstruct Spring untuk melakukan semua pekerjaan inisialisasi dan metode ini berjalan sebelum @Test mana pun dijalankan