如何在spring-boot应用程序的junit中调用ApplicationContextInitializer

Posted

技术标签:

【中文标题】如何在spring-boot应用程序的junit中调用ApplicationContextInitializer【英文标题】:How to invoke ApplicationContextInitializer in junit of spring-boot application 【发布时间】:2018-07-19 06:21:21 【问题描述】:

我是 spring-boot 的新手,并基于squiggly 实现了一个带有动态实体过滤的简单应用程序。一切正常,除了我无法制作一个 junit 来测试该功能。我测试了很多在网上找到的解决方案,但没有一个有效。

我的应用程序已按照 squiggly 文档中的建议进行初始化:

@SpringBootApplication
public class Application 
   @Bean
   public FilterRegistrationBean squigglyRequestFilter() 
     FilterRegistrationBean filter = new FilterRegistrationBean();
     filter.setFilter(new SquigglyRequestFilter());
     filter.setOrder(1);
     return filter;
   

   public static void main(String[] args) 
     new MyApplicationContextInitializer().initialize(SpringApplication.run(Application.class, args));
   


public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> 

    @Override
    public void initialize(ConfigurableApplicationContext context) 
        //context.refresh()
        Iterable<ObjectMapper> objectMappers = context.getBeansOfType(ObjectMapper.class).values();

        Squiggly.init(objectMappers, new RequestSquigglyContextProvider());

        ObjectMapper objectMapper = Iterables.getFirst(objectMappers, null);

        // Enable Squiggly for Jackson message converter
        if (objectMapper != null) 
            for (MappingJackson2HttpMessageConverter converter : context.getBeansOfType(MappingJackson2HttpMessageConverter.class).values()) 
                converter.setObjectMapper(objectMapper);
            
        
    

这是我实现的测试:

@RunWith(SpringRunner.class)
@SpringBootTest()
@ContextConfiguration(initializers = MyApplicationContextInitializer.class)
@AutoConfigureMockMvc
public class SimpleTest 

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testEntityFiltering() throws Exception 
        this.mockMvc.perform(get("/v1/issues").param("fields", "id"))
            .andExpect(status().isOk())
            // There should be only one field in the returned objects
            .andExpect(jsonPath("$[0].length()").value(1));
    

当我运行该测试时,我得到以下异常:

    java.lang.IllegalStateException: Failed to load ApplicationContext
    ...
    Caused by: java.lang.IllegalStateException: org.springframework.web.context.support.GenericWebApplicationContext@4116aac9 has not been refreshed yet
        at org.springframework.context.support.AbstractApplicationContext.assertBeanFactoryActive(AbstractApplicationContext.java:1067) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1187) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at com.renault.api.examples.springboot.MyApplicationContextInitializer.initialize(MyApplicationContextInitializer.java:28) ~[classes/:na]
        at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:567) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
        at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:338) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:301) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
        at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) ~[spring-boot-test-1.5.9.RELEASE.jar:1.5.9.RELEASE]
        at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) ~[spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ~[spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
        ... 25 common frames omitted

如果我取消注释 MyApplicationContextInitializer.initialize 中的 //context.refresh 行,我会收到以下异常:

java.lang.IllegalStateException: Failed to load ApplicationContext
  ...
Caused by: java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once
    at org.springframework.context.support.GenericApplicationContext.refreshBeanFactory(GenericApplicationContext.java:263) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:614) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:515) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120) ~[spring-boot-test-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) ~[spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ~[spring-test-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 25 common frames omitted

如果去掉@ContextConfiguration注解,测试失败,因为没有安装实体过滤器。

看来 *** 是我完成这项工作的最后机会......

【问题讨论】:

【参考方案1】:

有点晚了,但你可以尝试将 context.initializer.classes=your.package.MyApplicationContextInitializer 放在 src/test/resources/application.properties 中

【讨论】:

对我没有帮助。

以上是关于如何在spring-boot应用程序的junit中调用ApplicationContextInitializer的主要内容,如果未能解决你的问题,请参考以下文章

如何使用junit在spring-boot中测试常见错误ErrorController

spring-boot2.0 单元测试JUnit4

Spring-boot,使用不同配置文件的 JUnit 测试

在 junit 测试中禁用 RedisHttpSessionConfiguration

Spring-boot官方案例分析之data-jpa

基于spring-boot的应用程序的单元+集成测试方案