web-dev-qa-db-ja.com

@BeforeClassと継承-実行の順序

抽象ベースクラスがあり、これを単体テスト(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)                // <-/
84

abstractクラスに_@BeforeClass_を置かないでください。各サブクラスから呼び出します。

_abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
_

TestNGには @BeforeClass(dependsOnMethods={"doInitialization"}) -試してみてください。

41
Bozho

edit:以下の回答はJUnitに対するものですが、ここに残しておきますとにかく、それは役に立つかもしれないからです。

JUnit api :「スーパークラスの@BeforeClassメソッドは、現在のクラスの前に実行されます。」

これをテストしましたが、うまくいくようです。

ただし、@ Odysが以下で言及するように、JUnitには異なる名前の2つのメソッドが必要です親がシャドウイングされるためです。

94
Fortega

publicを抽象クラスに追加し、TestNG(6.0.1)はdoTestsの前にdoInitialization()を実行しました。クラスAからpublicを削除すると、TestNGはdoInitialization()を実行しません。

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}
7
Paul

5.11であなたの例を試したところ、基本クラスの@BeforeClassが最初に呼び出されました。

Testng.xmlファイルを投稿できますか? AとBの両方を指定しているのに、Bだけが必要な場合があります。

Testng-usersメーリングリストでフォローアップしてください。問題を詳しく調べることができます。

-セドリック

6
Cedric Beust

私はちょうどこれを経て、これを達成するためのもう1つの方法を見つけました。抽象クラスの@BeforeClassまたは@BeforeMethodalwaysRunを使用するだけで、期待どおりに機能します。

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}
3
Konrad Garus

For JUnit:@fortegaが述べたように:JUnit apiによると:「スーパークラスの@BeforeClassメソッドは、現在のクラスの前に実行されます。」

ただし、注意してください両方のメソッドに同じ名前を付けない。この場合、親メソッドは子親によって非表示になるためです。 ソース

2

実行時:JUnitCore.runClasses(TestClass.class);子の前に親を適切に実行します(super.SetUpBeforeClass();) Eclipseから実行する場合:何らかの理由で、基本クラスの実行に失敗します。回避策:基本クラスを明示的に呼び出します:(BaseTest.setUpBeforeClass();)アプリケーションから実行する場合は、基本クラスにフラグを付けて、それを確認しますすでにセットアップされているかどうか。したがって、両方の可能な方法(個人テスト用のEclipseから、ビルドリリース用のANTなど)で実行した場合、1回だけ実行されます。

これはEclipseのバグ、または少なくとも予期しない結果のようです。

2
Steve

インポート文を確認してください。そのはず

import org.testng.annotations.BeforeClass;

じゃない

import org.junit.BeforeClass;

1
nishantrevo

dependsOnMethodを使用できます。

例えば春の場合(AbstractTestNGSpringContextTests

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
1
Sandeep Jindal

@BeforeClassメソッドに、空のspecificBeforeClass()メソッドを呼び出させてください。このメソッドは、次のようなサブクラスによって上書きされる場合とされない場合があります。

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}
1
Tatome

これは私のために働く-

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}
0
srikar

ここには別の簡単な解決策があります。

私の特定の状況は、スーパークラスの「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
    }
};

これがお役に立てば幸いです。これにより、「逆」の順序で静的セットアップを効果的に実行できます。

0
vikingsteve

スーパークラスのBeforeClassアノテーション付きメソッドから呼び出される、スーパークラスで抽象メソッドdoSpecialInit()を作成してみませんか。

したがって、クラスを継承する開発者は、このメソッドを実装する必要があります。

0
Ludo

今日、似たような問題に直面しましたが、唯一の違いは基本クラスが抽象的ではなかったことです

これが私のケースです

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 実行しない 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.doSpecificInitialization()
  • B.doTests()
0
rodikno