beforeClass والميراث - ترتيب التنفيذ
-
22-09-2019 - |
سؤال
لدي فئة قاعدة مجردة ، والتي أستخدمها كقاعدة لاختبارات وحدتي (TestNG 5.10). في هذه الفئة ، أقوم بتهيئة البيئة بأكملها للاختبارات الخاصة بي ، وإعداد تعيينات قاعدة البيانات ، وما إلى ذلك. تحتوي هذه الفئة المجردة على طريقة مع أ @BeforeClass
التعليق التوضيحي الذي يفعل التهيئة.
بعد ذلك ، أقدم هذا الفصل بفئات محددة لدي @Test
الأساليب وأيضا @BeforeClass
طُرق. تقوم هذه الطرق بتهيئة البيئة الخاصة بالفئة (على سبيل المثال ، وضع بعض السجلات في قاعدة البيانات).
كيف يمكنني فرض ترتيب محدد من @BeforeClass
أساليب مشروحة؟ أحتاج إلى تنفيذ تلك من فئة القاعدة التجريدية قبل تلك الفئة الممتدة.
مثال:
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@BeforeClass
doSpecificInitialization() {...}
@Test
doTests() {...}
}
الترتيب المتوقع:
A.doInitialization
B.doSpecificInitialization
B.doTests
الترتيب الفعلي:
B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization // <---not executed
B.doTests) // <-/
المحلول
لا تضع @BeforeClass
على ال abstract
صف دراسي. نسميها من كل فئة فرعية.
abstract class A {
void doInitialization() {}
}
class B extends A {
@BeforeClass
void doSpecificInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}
يبدو أن Testng لديه @BeforeClass(dependsOnMethods={"doInitialization"})
- جربها.
نصائح أخرى
تعديل: الجواب أدناه هو جونيت, ، لكنني سأترك الأمر هنا على أي حال ، لأنه قد يكون مفيدًا.
بحسب ال JUNIT API: "سيتم تشغيل أساليب BeboReClass من الفئات الفائقة قبل تلك الفئة الحالية."
لقد اختبرت هذا ، ويبدو أنه يعمل بالنسبة لي.
ومع ذلك ، كما يذكر Odys أدناه ، بالنسبة إلى Junit ، تحتاج إلى الحصول على طريقتان سميتين بشكل مختلف على الرغم من أن القيام بخلاف ذلك سيؤدي إلى تشغيل طريقة الفئة الفرعية فقط لأن الوالد سيتم تظليله.
أضفت public
إلى الفئة التجريدية و testng (6.0.1) نفذت doinitialization () من قبل doTests
. لا يتم تنفيذ testng doInitialization()
إذا أزلت public
من الفئة أ
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
لقد جربت مثالك فقط مع 5.11 وأحصل على @beforeclass من الفئة الأساسية التي تم استدعاؤها أولاً.
هل يمكنك نشر ملف testng.xml الخاص بك؟ ربما تحدد كل من A و B ، في حين أن B ضروري فقط.
لا تتردد في المتابعة على قائمة المراسلين للمستخدمين ، ويمكننا إلقاء نظرة فاحصة على مشكلتك.
- سيدريك
لقد مررت للتو ووجدت طريقة أخرى لتحقيق ذلك. فقط استخدم alwaysRun
على @BeforeClass
أو @BeforeMethod
في الفصل التجريدي ، يعمل كما تتوقع.
public class AbstractTestClass {
@BeforeClass(alwaysRun = true)
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
}
عندما أركض من: junitcore.runclasses (testclass.class) ؛سوف ينفذ الوالد بشكل صحيح ، قبل الطفل (لا تحتاج super.setupbeforeClass () ؛) إذا قمت بتشغيله من Eclipse: لسبب ما فشل في تشغيل الفئة الأساسية. العمل حوله: اتصل بالفئة الأساسية بشكل واضح: ((BASETEST.SETUPBEFORECLASS () ؛) قد ترغب في الحصول على علامة في الفئة الأساسية في حالة تشغيله من التطبيق ، لتحديد ما إذا كان الإعداد بالفعل أم لا. لذلك يتم تشغيله مرة واحدة فقط إذا قمت بتشغيله عبر كلتا الأساليب الممكنة (مثل من Eclipse للاختبار الشخصي ، ومن خلال ANT لإصدار البناء).
يبدو أن هذا خطأ مع الكسوف ، أو على الأقل نتائج غير متوقعة ..
ل Junit: كما ذكرت @"
لكن كن حريص عدم تسمية كلتا الطريقتين بنفس الاسم. لأنه في هذه الحالة سيتم إخفاء طريقة الوالدين من قبل والد الطفل. مصدر.
ماذا عن وجود طريقة beboReClass الخاصة بك ، استدعاء طريقة فارغة foreClass () التي قد تتم نسخها أو لا تتم نسخها بواسطة فئات فرعية مثل ذلك:
public class AbstractTestClass {
@BeforeClass
public void generalBeforeClass() {
// do stuff
specificBeforeClass();
}
protected void specificBeforeClass() {}
}
public class SpecificTest {
@Override
protected void specificBeforeClass() {
// Do specific stuff
}
// Tests
}
dependsOnMethod
من الممكن استخدامه.
على سبيل المثال في حالة الربيع (AbstractTestNGSpringContextTests
)
@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
تحقق من بيان الاستيراد الخاص بك. يجب أن يكون
import org.testng.annotations.BeforeClass;
ليس
import org.junit.BeforeClass;
لماذا لا تحاول إنشاء طريقة مجردة dospecialinit () في فئتك الفائقة ، والتي تسمى من طريقة BeforeClass المشروح في الفئة الفائقة.
لذا فإن تطوير المراوغة ويرث صفك يجبر على تنفيذ هذه الطريقة.
هناك حل سهل آخر هنا.
وضعي الخاص هو أنني بحاجة إلى ضخ الخدمات الوهمية من "Beforeclass" في الفئة الفرعية قبل تنفيذ "BeforeClass" في الفئة الفائقة.
للقيام بذلك - ببساطة استخدم أ @ClassRule
في الفئة الفرعية.
فمثلا:
@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
}
};
آمل أن يساعد هذا. هذا يمكن أن ينفذ بشكل فعال الإعداد الثابت في ترتيب "عكسي".
لقد واجهت مشكلة مماثلة اليوم ، كان الفرق الوحيد هو أن الطبقة الأساسية لم تكن مجردة
ها هي حالتي
public class A {
@BeforeClass
private void doInitialization() {...}
}
public class B extends A {
@BeforeClass
private void doSpecificInitialization() {...}
@Test
public void doTests() {...}
}
حدث ذلك أ @BeforeClass
لم يتم تنفيذ الطريقة من الفئة A أبدًا.
- A.Doinitialization () -> لم يتم تنفيذ هذا بصمت أبدًا
- B.DospecificInitialization ()
- B.Dotests ()
اللعب مع معدلات الخصوصية وجدت أن testng لن ينفذ أ @BeforeClass
طريقة مشروحة من الطبقة الموروثة إذا كانت الطريقة غير مرئية من فئة من الدرجة
لذلك هذا سوف يعمل:
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() {...}
}
نتيجة لذلك يحدث: يحدث:
- A.Doinitialization ()
- B.DospecificInitialization ()
- B.Dotests ()
هذا يعمل بالنسبة لي -
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
في حالتي (Junit) لدي نفس الأساليب التي تسمى الإعداد () في الفئة الأساسية والفئة المشتقة. في هذه الحالة فقط يتم استدعاء طريقة الفئة المشتقة ، وأنا أتصل بها طريقة الفئة الأساسية.
قد تكون طريقة أفضل وأنظف لتحقيق ذلك باستخدام الميراث على النحو التالي -
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}