jUnitの複数のRunWithステートメント


113

単体テストを作成JUnitParamsRunnerしてMockitoJUnitRunner、1つのテストクラスで使用したいと考えています。

残念ながら、以下は機能しません。

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

1つのテストクラスでMockitoとJUnitParamsの両方を使用する方法はありますか?



2
良い例もここにあります:blog.project13.pl/index.php/coding/1077/...
falsarella

回答:


110

仕様によると、同じ注釈付き要素に同じ注釈を2回置くことができないため、これを行うことはできません。

それで、解決策は何ですか?解決策は、@RunWith()あなたが立つことができないランナーを持つ1つだけを置き、他のものを他のものと交換することです。あなたの場合、私はあなたがそれを削除MockitoJUnitRunnerしてプログラム的に行うと思います。

実際、それが実行する唯一のことは次のとおりです。

MockitoAnnotations.initMocks(test);

テストケースの始めに。したがって、最も簡単な解決策は、このコードをsetUp()メソッドに配置することです。

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

私はわからないが、おそらくあなたは、フラグを使用して、このメソッドの複数の呼び出しを回避する必要があります。

private boolean mockInitialized = false;
@Before
public void setUp() {
    if (!mockInitialized) {
        MockitoAnnotations.initMocks(this);
        mockInitialized = true;  
    }
}

ただし、JUntのルールを使用して再利用可能なソリューションを実装することもできます。

public class MockitoRule extends TestWatcher {
    private boolean mockInitialized = false;

    @Override
    protected void starting(Description d) {
        if (!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;  
        }
    }
}

次の行をテストクラスに追加します。

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

このテストケースは、任意のランナーで実行できます。


12
のチェックmockInitializedが間違っています。あなたはすべてのtetstのために新鮮なモックを持ちたいです。
BetaRide

1
@BetaRide、それはあなたのニーズに依存します。毎回モックを初期化したい場合もあれば、そうでない場合もあります。
AlexR

クラスファイルごとに1回設定する場合は、Beforeの代わりにBeforeClassを使用できます。BeforeClassは、テストファイルごとに1回だけ呼び出されます。
InfernalRapture

56

JUnit 4.7およびMockito 1.10.17以降、この機能は組み込まれています。そこにあるorg.mockito.junit.MockitoRuleクラスは。それをインポートして行を追加するだけです

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

あなたのテストクラスに。


2
古いバージョンのMockito(1.10.5までのようです)を使用する必要があります:@Rule public MockitoJUnitRule mockito = new MockitoJUnitRule(this);
Cliff Sun

MockitoAnnotations.initMocks(this)モックを作成するのは非常に遅いです。最も効率的な方法は、@ Runwith(MockitoJunitRunner.class)を使用することです
ant2009

16

このソリューションは、このmockitoの例だけでなく、あらゆるランナーに有効です。例えば; Springの場合は、ランナークラスを変更し、必要な注釈を追加するだけです。

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

    @Test
    public void subRunner() throws Exception {
        JUnitCore.runClasses(TestMockitoJUnitRunner.class);
    }

    @RunWith(MockitoJUnitRunner.class)
    public static class TestMockitoJUnitRunner {
    }
}

DatabaseModelTestJUnitによって実行されます。TestMockitoJUnitRunner(ロジックによって)これに依存し、呼び出し中にメソッドのメインで実行さ@TestますJUnitCore.runClasses(TestMockitoJUnitRunner.class)。この方法により、static class TestMockitoJUnitRunnerサブランナーが実行される前にメインランナーが正しく開始され@RunWith、依存するテストクラスを持つ複数のネストされたアノテーションが効果的に実装されます。

また、https://bekce.github.io/junit-multiple-runwith-dependent-tests


3
JUnitCore.runClasses()結果を検査せずに呼び出すと、内部テストからのエラーを隠すリスクがあります。assert(JUnitCore.runClasses(TestMockitoJUnitRunner.class).wasSuccessful());少なくともエラーを報告します
Robotnik '


2

私の場合、私は春の豆でいくつかの方法を模擬しようとしていました

MockitoAnnotations.initMocks(test);

動作しません。代わりに、次のようにxmlファイル内でmockメソッドを使用して構築するBeanを定義する必要があります。

...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...

次のように、テストクラス内に自動配線されたBeanを追加します。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
    ...
    @Autowired
    private ClassWantedToBeMocked classWantedToBeMocked;
    ...
    when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
    ...
}

0

このリンクをチェックしてくださいhttps://bekce.github.io/junit-multiple-runwith-dependent-tests/ このアプローチを使用して、@ RunWith(Parameterized.class)-外部ランナー-@RunWith(MockitoJUnitRunner.class)を組み合わせました-インナーランナー。追加する必要があった唯一の微調整は、内部/ネストされたランナー/クラスがアクセスできるように、外部クラス/ランナーのメンバー変数を静的にすることでした。運を楽しんでください。


0

SWTBotJunit4ClassRunnerorg.junit.runners.Parameterizedを同時に実行したいのですが、パラメトリックテストがあり、SWTテストが失敗したときにスクリーンショットを撮りたいです(スクリーンショット機能はSWTBotJunit4ClassRunnerによって提供されます)。@bekceの答えは素晴らしく、最初にそのルートに行きたかったのですが、どちらかと言えば議論を通過するのは奇抜でした。または、サブクラスでパラメーター化し、正確なテストが成功/失敗した情報を失い、最後のスクリーンショットのみを取得します(スクリーンショット名はテスト自体から名前を取得するため)。どちらにしても、それは少し厄介でした。

私の場合、SWTBotJunit4ClassRunnerは十分に単純なので、クラスのソースコードを複製し、それに独自の名前ParametrizedScreenshotRunnerを付け、元の場所がTestRunnerを拡張していたところ、私のクラスはParameterizedクラスを拡張しているので、本質的には自分のランナーを使用できます前の2つの代わりに。スクリーンショット機能を実装しながら、自分のランナーをパラメーター化ランナーの上に拡張します。テストではこの「ハイブリッド」ランナーを使用し、すべてのテストがすぐに期待どおりに機能します(テスト内で何も変更する必要はありません)。

これは次のようになります(簡潔にするために、リストからすべてのコメントを削除しました)。

package mySwtTests;

import org.junit.runners.Parameterized;
import org.eclipse.swtbot.swt.finder.junit.ScreenshotCaptureListener;
import org.junit.runner.notification.RunListener;
import org.junit.runner.notification.RunNotifier;

public class ParametrizedScreenshotRunner extends TestRu Parameterized {

    public ParametrizedScreenshotRunner(Class<?> klass) throws Throwable {
        super(klass);
    }

    public void run(RunNotifier notifier) {
        RunListener failureSpy = new ScreenshotCaptureListener();
        notifier.removeListener(failureSpy); // remove existing listeners that could be added by suite or class runners
        notifier.addListener(failureSpy);
        try {
            super.run(notifier);
        } finally {
            notifier.removeListener(failureSpy);
        }
    }
}

-15

これを試すこともできます:

@RunWith(JUnitParamsRunner.class)
public class AbstractTestClass {
  // some tests
}

@RunWith(MockitoJUnitRunner.class)
public class DatabaseModelTest extends AbstractTestClass {
  // some tests
}

2
これは機能せず、サブクラスのアノテーションのみが処理されます。
PaulNUK、2015年

機能しません-MockitoJUnitRunnerアノテーションのみが考慮されます
Przemek Bielicki
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.