Java Spring boot如何测试WebServerInitialized事件
我试图在应用程序向服务注册表注册时测试应用程序的功能。只有当应用程序具有完整的web上下文(即,Java Spring boot如何测试WebServerInitialized事件,java,spring-cloud,Java,Spring Cloud,我试图在应用程序向服务注册表注册时测试应用程序的功能。只有当应用程序具有完整的web上下文(即,springbootstarterweb位于类路径上,并且servlet未被模拟)时,才会发生这种情况。这是通过spring cloud commons控制的 简单测试 所有测试应执行以下操作: 1) Bring up Web App 2) Verify auto-registration w/ service registry event fired 3) Manually force close
springbootstarterweb
位于类路径上,并且servlet未被模拟)时,才会发生这种情况。这是通过spring cloud commons
控制的
简单测试
所有测试应执行以下操作:
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
使创建完整的web上下文变得非常容易,这非常好。但我无法关闭应用程序中期测试以强制注销
@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()
非常有效,但是configures中的web上下文有一个模拟servlet,并且不会触发自动注册所需的WebInitializeEvent
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);
});
}
这几乎可以工作,但会产生一个
MockServletContext
bean,我认为它无法从spring cloud commons
触发必要的WebServerInitializeEvent
。这种方法如何引导一个真实、完整的嵌入式tomcat服务器?按照Spencer的建议,我使用spring应用程序生成器创建了一个完整的web应用程序。我在自动配置模块之外也做了这件事——在类路径上创建了一个名为“集成测试”的新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文件,如下所示。此外,确保手动关闭每个测试的应用程序上下文也很重要
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());
}
这在很大程度上是一个集成测试。在SpringCloud的某些情况下,我们发现最好的方法是
SpringApplication.run()
。您可以在@SpringBootTest
中执行此操作吗?如果是这样,您将如何构建应用程序注销时的验证?例如,你还会调用app.close()
?