Как я могу запустить код в JUnit до запуска Spring? - PullRequest
0 голосов
/ 18 апреля 2019

Как мне выполнить код в моем @RunWith(SpringRunner.class) @SpringBootTest(classes = {...}) тесте JUnit перед запуском Spring?

Этот вопрос задавался несколько раз (например, 1 , 2 ) но всегда "решался" по той или иной рекомендации по конфигурации, а не с универсальным ответом.Пожалуйста, не спрашивайте, что я собираюсь сделать в этом коде, а просто предложите чистый способ сделать это.

Попытка до сих пор и не удалось:

Расширить SpringJUnit4ClassRunner, чтобы получить класс, конструктор которого может запускать пользовательский код перед инициализацией Spring.Сбой, потому что super(testClass) должен быть вызван первым делом и уже делает много вещей, которые мешают.

Расширьте Runner, чтобы получить класс, который делегирует SpringRunnerвместо того, чтобы наследовать это.Этот класс может запускать пользовательский код в своем конструкторе до фактического создания экземпляра SpringRunner.Однако эта настройка завершается с ошибочными сообщениями об ошибках, такими как java.lang.NoClassDefFoundError: javax / servlet / SessionCookieConfig ."Obscure", потому что мой тест не имеет веб-конфигурации и поэтому не должен вмешиваться в сеансы и файлы cookie.

Добавление ApplicationContextInitializer, которое запускается до того, как Spring загрузит свой контекст.Эти вещи легко добавить к фактическому @SpringApplication, но трудно добавить в Junit.Они также довольно поздно в этом процессе, и большая часть Spring уже началась.

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Один из способов сделать это - исключить SpringRunner и использовать эквивалентную комбинацию из SpringClassRule и SpringMethodRule. Затем вы можете обернуть SpringClassRule и выполнить свои действия до того, как он сработает:

public class SomeSpringTest {

    @ClassRule
    public static final TestRule TestRule = new TestRule() {
            private final SpringClassRule springClassRule =
                new SpringClassRule();

            @Override
            public Statement apply(Statement statement, Description description) {
                System.out.println("Before everything Spring does");
                return springClassRule.apply(statement, description);
            }
        };

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @Test
    public void test() {
        // ...
    }
}

(протестировано с версией 5.1.4. Release Spring)

Я не думаю, что вы можете получить больше "раньше", чем это. Что касается других опций, вы также можете проверить @BootstrapWith и @TestExecutionListeners аннотации.

0 голосов
/ 07 мая 2019

Дополнение комментария Джанниса по этому вопросу, возможность создать альтернативный бегун JUnit и позволить ему делегировать SpringRunner работает :

public class AlternativeSpringRunner extends Runner {

    private SpringRunner springRunner;

    public AlternativeSpringRunner(Class testClass) {
        doSomethingBeforeSpringStarts();
        springRunner = new SpringRunner(testClass);
    }

    private doSomethingBeforeSpringStarts() {
        // whatever
    }

    public Description getDescription() {
        return springRunner.getDescription();
    }

    public void run(RunNotifier notifier) {
        springRunner.run(notifier);
    }

}

Основано на spring-test4.3.9.RELEASE, мне пришлось переопределить spring-core и spring-tx, плюс javax.servlet servlet-api с более высокими версиями, чтобы эта работа работала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...