我正在尝试测试应用程序在服务注册中心注册时出现的功能。这只会发生在应用程序有一个完整的网络上下文(即。spring-boot-starter-web在类路径上,servlet没有被模拟)。这是通过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使得创建完整的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()很好,但配置中的web上下文有一个模拟servlet,并且不触发自动注册所需的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);
});
}几乎可以使用,但是会产生一个MockServletContext bean,我认为它无法从spring-cloud-commons触发必需的WebServerInitializedEvent。这种方法如何引导一个真正的、完整的嵌入式tomcat服务器?
发布于 2019-05-08 01:47:01
按照Spencer的建议,我使用spring应用程序构建器创建了一个完整的web应用程序。我还在自动配置模块之外这样做--在类路径上使用spring-boot-starter-web创建了一个名为“集成测试”的新maven子模块。
@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());
}https://stackoverflow.com/questions/55463222
复制相似问题