Saya memiliki kelas dasar abstrak, yang saya gunakan sebagai dasar untuk pengujian unit saya (TestNG 5.10). Di kelas ini, saya menginisialisasi seluruh lingkungan untuk pengujian saya, menyiapkan pemetaan database, dll. Kelas abstrak ini memiliki metode dengan @BeforeClass
anotasi yang melakukan inisialisasi.
Selanjutnya, saya memperluas kelas itu dengan kelas tertentu di mana saya memiliki @Test
metode dan juga @BeforeClass
metode. Metode ini melakukan inisialisasi lingkungan khusus kelas (misalnya, memasukkan beberapa catatan ke dalam database).
Bagaimana saya dapat menerapkan urutan tertentu dari @BeforeClass
metode beranotasi? Saya membutuhkan yang dari kelas dasar abstrak untuk dieksekusi sebelum kelas yang diperluas.
Contoh:
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@BeforeClass
doSpecificInitialization() {...}
@Test
doTests() {...}
}
Pesanan yang diharapkan:
A.doInitialization
B.doSpecificInitialization
B.doTests
Urutan sebenarnya:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
sumber
dependsOnMethods
solusi melakukan trik. Meskipun saya lebih suka pendekatan "superclass first" ...edit: Jawaban di bawah ini adalah untuk JUnit , tetapi saya akan meninggalkannya di sini, karena ini bisa membantu.
Menurut JUnit api : "Metode superclass @BeforeClass akan dijalankan sebelum kelas saat ini."
Saya menguji ini, dan tampaknya berhasil untuk saya.
Namun, seperti yang disebutkan @Odys di bawah ini, untuk JUnit Anda harus memiliki dua metode yang diberi nama berbeda meskipun melakukan sebaliknya hanya akan menghasilkan metode subclass yang dijalankan karena induknya akan dibayangi.
sumber
Saya menambahkan
public
ke kelas abstrak dan TestNG (6.0.1) mengeksekusi doInitialization () sebelumnyadoTests
. TestNG tidak dijalankandoInitialization()
jika saya menghapuspublic
dari kelas A.public abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Test doTests() {...} }
sumber
B
juga memiliki@BeforeClass
metode -annotated, seperti dalam kasus OP.Saya baru saja mencoba contoh Anda dengan 5.11 dan saya mendapatkan @BeforeClass dari kelas dasar yang dipanggil terlebih dahulu.
Bisakah Anda memposting file testng.xml Anda? Mungkin Anda menentukan A dan B di sana, sementara hanya B yang diperlukan.
Jangan ragu untuk menindaklanjuti milis pengguna testng dan kami dapat melihat lebih dekat masalah Anda.
- Cedric
sumber
Saya baru saja melalui ini dan menemukan satu cara lagi untuk mencapai ini. Cukup gunakan
alwaysRun
di@BeforeClass
atau@BeforeMethod
di kelas abstrak, berfungsi seperti yang Anda harapkan.public class AbstractTestClass { @BeforeClass(alwaysRun = true) public void generalBeforeClass() { // do stuff specificBeforeClass(); } }
sumber
Ketika saya menjalankan dari: JUnitCore.runClasses (TestClass.class); Ini akan mengeksekusi orang tua dengan benar, sebelum anak (Anda tidak perlu super.SetUpBeforeClass (); ) Jika Anda menjalankannya dari Eclipse: Untuk beberapa alasan gagal menjalankan kelas dasar. Solusi: Panggil kelas dasar secara eksplisit: ( BaseTest.setUpBeforeClass (); ) Anda mungkin ingin memiliki bendera di kelas dasar jika Anda menjalankannya dari aplikasi, untuk menentukan apakah sudah disiapkan atau belum. Jadi itu hanya berjalan sekali jika Anda menjalankannya melalui kedua metode yang memungkinkan (seperti dari gerhana untuk pengujian pribadi, dan melalui ANT untuk rilis build).
Tampaknya ini bug dengan Eclipse, atau setidaknya hasil yang tidak diharapkan ..
sumber
Untuk JUnit : Seperti yang telah disebutkan @fortega: Menurut JUnit api: "Metode superclass @BeforeClass akan dijalankan sebelum kelas saat ini."
Namun hati-hati jangan sampai memberi nama kedua metode tersebut dengan nama yang sama . Karena dalam kasus ini metode induk akan disembunyikan oleh anak induk. Sumber .
sumber
Bagaimana jika metode @BeforeClass Anda memanggil metode specificBeforeClass () kosong yang mungkin atau mungkin tidak ditimpa oleh sub kelas seperti ini:
public class AbstractTestClass { @BeforeClass public void generalBeforeClass() { // do stuff specificBeforeClass(); } protected void specificBeforeClass() {} } public class SpecificTest { @Override protected void specificBeforeClass() { // Do specific stuff } // Tests }
sumber
dependsOnMethod
dapat digunakan.misalnya dalam kasus Musim Semi (
AbstractTestNGSpringContextTests
)@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
sumber
Periksa pernyataan impor Anda. Harus
import org.testng.annotations.BeforeClass;
tidak
import org.junit.BeforeClass;
sumber
Ini bekerja untuk saya -
abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Override @BeforeClass doInitialization() { //do class specific init } @Test doTests() {...} }
sumber
Mengapa Anda tidak mencoba membuat metode abstrak doSpecialInit () di kelas super Anda, yang dipanggil dari metode beranotasi BeforeClass di superclass.
Jadi, pengembang yang mewarisi kelas Anda dipaksa untuk mengimplementasikan metode ini.
sumber
Ada solusi mudah lainnya di sini.
Situasi khusus saya adalah bahwa saya perlu menyuntikkan layanan tiruan dari "BeforeClass" di subclass sebelum "BeforeClass" di superclass tersebut dijalankan.
Untuk melakukan ini - cukup gunakan a
@ClassRule
di subclass.Sebagai contoh:
@ClassRule public static ExternalResource mocksInjector = new ExternalResource() { @Override protected void before() { // inject my mock services here // Note: this is executed before the parent class @BeforeClass } };
Saya harap ini membantu. Ini secara efektif dapat menjalankan pengaturan statis dalam urutan "terbalik".
sumber
Saya telah menghadapi masalah serupa hari ini, satu-satunya perbedaan adalah kelas Base tidak abstrak
Ini kasus saya
public class A { @BeforeClass private void doInitialization() {...} } public class B extends A { @BeforeClass private void doSpecificInitialization() {...} @Test public void doTests() {...} }
Ternyata
@BeforeClass
metode dari kelas A tidak pernah dijalankan.Bermain dengan pengubah privasi saya menemukan bahwa TestNG tidak akan mengeksekusi sebuah
@BeforeClass
metode dijelaskan dari kelas mewarisi jika metode ini tidak terlihat dari kelas-pewarisJadi ini akan berhasil:
public class A { @BeforeClass private void doInitialization() {...} } public class B extends A { @BeforeClass //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors protected void doSpecificInitialization() {...} @Test public void doTests() {...} }
Akibatnya hal berikut terjadi:
sumber
Dalam kasus saya (JUnit), saya memiliki metode yang sama yang disebut setup () di kelas dasar dan kelas turunan. Dalam hal ini hanya metode kelas turunan yang dipanggil, dan saya menyebutnya metode kelas dasar.
sumber
Cara yang lebih baik dan lebih bersih untuk mencapai ini dengan menggunakan warisan mungkin sebagai berikut -
abstract class A { @BeforeClass void doInitialization() {} } class B extends A { @Override @BeforeClass void doInitialization() { super.doInitialization(); } @Test void doTests() {} }
sumber