Spring boot: Unit test and Config file

2019-07-02 11:06发布

问题:

I am doing unit tests for a rest controller, which is only a small part of a bigger application.
My test context isn't recognized by my application and I have the following exception : java.lang.IllegalStateException: Failed to load ApplicationContext

This is my test class:

Test RestController

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(locations = "classpath:/META-INF/spring/context-test.xml")
@WebIntegrationTest
public class MyRestControllerTest extends AbstractTransactionnalTest {

  @Autowired
  private IManager manager;

  @Test
  // my unit tests
}

The thing is that if instead of locations = "classpath:/META-INF/spring/context-test.xml" I use classes = Production.class with the following application class, it works fine:

@Configuration
@EnableAutoConfiguration
@EnableTransactionManagement
@EnableScheduling
@ImportResource({ "classpath:/META-INF/spring/context-production.xml" })
public class Production {
  // class content
}

I've read all the posts with similar problem and I know it is linked to the @Configuration and @EnableAutoConfiguration annotation however when I tried a custom configuration class which used these annotation and imported the settings from the context.xml it did not work.
I ideally wish not to add any configuration class and would like to only add a bean to my test-context.xml.
Is it possible to solve this issue with a bean in my context.xml or an annotation on TestRestController ?

Here is my stack trace:

java.lang.IllegalStateException: Failed to load ApplicationContext

    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
   ... 26 more
Caused by: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    ... 35 more
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:185)
    ... 39 more

Here is the bean I used to mock the manager in my test-context.xml :

<bean id="IManager"
        class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.service.impl.Manager"/>

Update :

I tried to used a custom manager mock where the database is replaced with a list.
If I remove the annotation @WebIntegrationTest, the application context loads correctly however I get another exception because the server isn't launched without the @WebIntegrationTest annotation.

I/O error on GET request for network address :Connection refused

I am running on spring 1.3.7.

回答1:

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests. Specifically @ContextConfiguration declares the application context resource locations or the annotated classes that will be used to load the context.

@ContextConfiguration("/test-config.xml") 
public class XmlApplicationContextTests { 
    // class body... 
}

Spring Boot provides a @SpringBootTest  annotation which can be used as an alternative to the standard spring-test @ContextConfiguration  annotation when you need Spring Boot features. The annotation works by creating the ApplicationContext used in your tests via SpringApplication.

You can use the webEnvironment attribute of @SpringBootTest to further refine how your tests will run.

Spring Boot’s @*Test annotations will search for your primary configuration automatically whenever you don’t explicitly define one.

The search algorithm works up from the package that contains the test until it finds a @SpringBootApplication or @SpringBootConfiguration annotated class. As long as you’ve structured your code in a sensible way your main configuration is usually found.

If you want to customize the primary configuration, you can use a nested @TestConfiguration class. Unlike a nested @Configuration class which would be used instead of a your application’s primary configuration, a nested @TestConfiguration class will be used in addition to your application’s primary configuration.

http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html 40.2