3

JUnit を使用してテスト自動化スイートを作成しようとしています。すべてのテストについて、ルールを作成したいと思います。このために、インターフェイスを作成し、その中にルールを配置しました。実行したいテストはすべて、そのインターフェースを実装する必要があります。コンパイラ エラーはスローされませんでしたが、私の Test クラスがそのインターフェイスを実装すると、これは機能しないようです。以下は私が作成したインターフェースです。

public interface IBaseTest {
    @Rule
    public TestRule test = new TestWatcher(){
        @Override
        protected void starting(Description description)
        {
            System.out.println("Starting Test: " + description);
        }
    };
}

または、上記をクラスとして作成し、そのクラスからすべてのテスト クラスを拡張することもできました。それを試してみたところ、完全に機能しましたが、他のクラスからテスト メソッドを拡張できなくなりました。

基本クラスから拡張せずに、すべてのテストに適用できるルールを作成する方法はありますか?

4

1 に答える 1

1

はい、私が知っている方法はありますが、余分なコードを書く必要があります。

まず、JUnit が TestRule を無視する理由は、インターフェイスで宣言されているため、静的 (および最終) であるためです。

この問題を克服するには、次のようなカスタム ランナーを作成する必要があります。

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public final class MyRunner extends BlockJUnit4ClassRunner {

    public MyRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<TestRule> getTestRules(Object target) {
        List<TestRule> testRules = super.getTestRules(target);
        testRules.addAll(getStaticFieldTestRules(target));
        return testRules;
    }

    private List<TestRule> getStaticFieldTestRules(Object target) {
        List<TestRule> testRules = new ArrayList<>();
        Class<?> clazz = target.getClass();
        for (Field f : clazz.getFields()) {
            if ((f.getModifiers() & Modifier.STATIC) != 0) {
                if (f.isAnnotationPresent(Rule.class)) {
                    try {
                        testRules.add((TestRule) f.get(target));
                    } catch (IllegalArgumentException | IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    }
                }
            }
        }
        return testRules;
    }
}

最後に、テストクラスに注釈を付けて、新しいカスタムランナーで実行すると、すべてが期待どおりになります...

import org.junit.runner.RunWith;

@RunWith(MyRunner.class)
public class Test implements IBaseTest {

    @org.junit.Test
    public void testName1() throws Exception {
    }

    @org.junit.Test
    public void testName2() throws Exception {

    }

}
于 2014-08-03T08:26:24.980 に答える