Spring boot как проверить событие WebServerInitialized - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь проверить работоспособность приложения, которое происходит, когда приложение регистрируется в реестре служб. Это происходит только тогда, когда приложение имеет полный веб-контекст (т. Е. spring-boot-starter-web находится на пути к классу, а сервлет не является поддельным). Это управляется через spring-cloud-commons AbstractAutoServiceRegistration .

Простой тест

Все, что должен сделать тест, это:

1) Bring up Web App
2) Verify auto-registration w/ service registry event fired
3) Manually force close app
4) Verify auto-deregistratoin occurred

Подход 1: @ SpringBootTest

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

@RunWith(SpringRunner.class)
@SpringBootTest(
        classes = MyAutoConfig.class,
        webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT
)
@EnableAutoConfiguration
public class DiscoverySpringCloudBootMinimalRegistrationTest {

@Test
public void register_deregister {
    // Force-close app to trigger dereigster (causes exception)
    ((ConfigurableApplicationContext) context).close();

    verify(registry, times(1)).register(autoRegistrationServiceRecord);
    verify(registry, times(1)).deregister(autoRegistrationServiceRecord);
}

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

..... contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]] is not active. This may be due to one of the following reasons: 1) the context was closed programmatically by user code; 2) the context was closed during parallel test execution either according to @DirtiesContext semantics or due to automatic eviction from the ContextCache due to a maximum cache size policy.

Подход 2: WebContextRunner

В этом подходе я избегаю @SpringBootTest и вручную настраиваю контекстный бегун. Это хорошо работает для вызова context.close(), но веб-контекст в конфигурациях имеет фиктивный сервлет и НЕ запускает WebInitializedEvent, необходимый для автоматической регистрации.

public class BasicAutoConfigTests {

    private WebApplicationContextRunner runner;

    @Test
    public void register_deregister() {

       runner = new WebApplicationContextRunner()
              .withConfiguration(
                    AutoConfigurations.of(MyAutoConfig.class));


       runner.run((context) -> {
          assertThat(context).hasNotFailed();

          ServiceRegistry registry = context.getBean(ServiceRegistry.class);
          ServiceRecord autoRegistration = context.getBean(MyServiceRecord.class);
          context.close();

          verify(registry, times(1)).register(autoRegistration);
          verify(registry, times(1)).deregister(autoRegistration);

      });
  }

Это почти работает , но в результате получается bean-компонент MockServletContext, который, как я полагаю, не может вызвать необходимый WebServerInitializedEvent из spring-cloud-commons. Как этот подход может загрузить подлинный, полный встроенный сервер Tomcat?

1 Ответ

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

Следуя совету Спенсера, я использовал конструктор приложений Spring для создания полноценного веб-приложения.Я также сделал это вне модуля автоконфигурации - создал новый подмодуль maven под названием «интеграционные тесты» с spring-boot-starter-web на пути к классам.

@Import(MyAutoConfig.class)
@SpringBootApplication
public class MinStarterBasicApp {

@Bean
ServiceRegistry serviceRegistry() {
    return mock(ServiceRegistry.class);
    }

    static ConfigurableApplicationContext setupWebApp(String... profiles){
        System.setProperty("spring.main.allow-bean-definition-overriding", "true");

        SpringApplication app = new SpringApplicationBuilder(MinStarterBasicApp.class)
                .web(WebApplicationType.SERVLET)
                .profiles(profiles)
                .build();
        return app.run();
    }
}

Где profiles позволяет мне передать в application.propertiesфайлы по имени, как показано ниже.Также важно убедиться, что мы вручную close контекст приложения для каждого теста.

public class StarterBasicAutoconfigTest {

    ConfigurableApplicationContext context;

    @After
    public void teardown() {
        if (context != null && context.isRunning())
            context.close();
    }


    @Test
    public void sometest() {
        context = MinStarterBasicApp.setupWebApp("profile1");

        ServiceRegistry registry = context.getBean(ServiceRegistry.class);
        context.close();

        Mockito.verify(registry, times(1)).register(any());
        Mockito.verify(registry, times(1)).deregister(any());
}
...