@beforeclassおよび継承 - 実行順序
-
22-09-2019 - |
質問
抽象的なベースクラスがあり、これを単体テストのベースとして使用しています(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: :「スーパークラスの@beforeclassメソッドは、現在のクラスの前に実行されます。」
私はこれをテストしました、そしてそれは私のために働いているようです。
ただし、@dodysが以下に述べているように、Junitの場合、 異なる名前の2つの方法 他の方法では、親が影になるため、サブクラスメソッドのみが実行されます。
追加した public
抽象クラスとtestng(6.0.1)は、doinitialization()を前に実行しました doTests
. 。 testngは実行されません doInitialization()
削除した場合 public
クラスAからAから
public abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Test
doTests() {...}
}
5.11であなたの例を試したところ、最初に呼び出された基本クラスの@beforeclassを取得します。
testng.xmlファイルを投稿できますか?たぶん、あなたはそこでAとBの両方を指定していますが、Bのみが必要です。
Testng-usersの郵送リストを自由にフォローアップしてください。あなたの問題を詳しく見ることができます。
- セドリック
私はちょうどこれを経験したばかりで、これを達成するもう1つの方法を見つけました。使用するだけです 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を介して)を使用して実行する場合にのみ1回実行されます。
これは、日食のバグ、または少なくとも予期しない結果のように見えます。
Junitの場合:@fortegaが述べたように:Junit APIによると、「スーパークラスの@beforeclassメソッドは、現在のクラスの前に実行されます。」
しかし、注意してください 同じ名前の両方の方法を名前にしないでください. 。この場合、親の方法は子の親によって隠されるためです。 ソース.
@beforeclassメソッドに、SOのようなサブクラスによって上書きされる場合と上書きされる可能性のある空のspecietalbeforeclass()メソッドを呼び出すのはどうですか。
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;
スーパークラスで抽象的なメソッドを作成して、superclassのbeforeclassアノテートメソッドから呼び出されてみませんか。
したがって、クラスを継承する開発者は、この方法を実装することを余儀なくされます。
ここには別の簡単な解決策があります。
私の特定の状況は、スーパークラスの「beforeclass」が実行される前に、サブクラスに「beforeclass」からモックサービスを注入する必要があることです。
これを行うには、単にaを使用します @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.depecificInitialization()
- b.detests()
プライバシー修飾子で遊ぶと、そのtestngがわかりました 実行しません a @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.depecificInitialization()
- b.detests()
これは私のために働きます -
abstract class A {
@BeforeClass
doInitialization() {...}
}
class B extends A {
@Override
@BeforeClass
doInitialization() {
//do class specific init
}
@Test
doTests() {...}
}
私の場合(Junit)、基本クラスと派生クラスにSetup()と呼ばれる同じ方法があります。この場合 それだけ 派生クラスのメソッドが呼び出され、基本クラスのメソッドと呼ばれます。
継承を使用してこれを達成するためのより良いよりクリーンな方法は、次のようになるかもしれません -
abstract class A {
@BeforeClass
void doInitialization() {}
}
class B extends A {
@Override
@BeforeClass
void doInitialization() {
super.doInitialization();
}
@Test
void doTests() {}
}