Возможно ли создать правило JUnit внутри интерфейса

Я пытаюсь создать набор автоматизации тестирования с помощью JUnit. Для всех тестов я хочу создать правило, для этого я создал интерфейс и поместил в него правило. Любые тесты, которые я хочу запустить, должны будут внедрить этот интерфейс. Однако он не выдавал никакой ошибки компилятора, однако, когда мой класс Test реализует этот интерфейс, это, похоже, не работает. Ниже приведен интерфейс, который я создал.

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

В качестве альтернативы, я мог бы создать вышеупомянутое как класс и расширить все мои тестовые классы из этого класса, я пробовал это, и он работал отлично, однако это помешало бы мне продлить мои тестовые методы из любого другого класса.

Есть ли способ создать правила, которые будут применимы для всех моих тестов, не распространяясь на базовый класс?

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; }
}
</testrule></testrule></testrule></testrule>

Наконец, аннотируйте свой тестовый класс для запуска с новым пользовательским бегуном, и все так, как вы ожидаете...

import org.junit.runner.RunWith;
@RunWith(MyRunner.class)
public class Test implements ********* { @org.junit.Test public void testName1() throws Exception { } @org.junit.Test public void testName2() throws Exception { }
}

licensed under cc by-sa 3.0 with attribution.