@WebAppConfiguration and @ContextConfiguration for Spring Boot + Thymeleaf

22,180

Thanks to @M.Deinum for helping me to realize that:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = Config.class)
public class ControllerTest {

...should be:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@SpringApplicationConfiguration(classes = Application.class)
public class ControllerTest {

I suppose that @ContextConfiguration is meant for integration tests in Spring, whereas @SpringApplicationConfiguration is meant for integration tests in Spring Boot.

According to the Javadoc for the latter:

Class-level annotation that is used to determine how to load and configure an ApplicationContext for integration tests.

Similar to the standard @ContextConfiguration but uses Spring Boot's SpringApplicationContextLoader.

Share:
22,180
Tommy Stanton
Author by

Tommy Stanton

Computer programmer and banjo picker

Updated on July 09, 2022

Comments

  • Tommy Stanton
    Tommy Stanton almost 2 years

    Given a Spring Boot + Thymeleaf web application (this is nearly identical to the Spring project's gs-consuming-rest "initial" code tree):

    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── hello
        │   │       ├── Application.java
        │   │       ├── Config.java
        │   │       └── Controller.java
        │   └── resources
        │       └── templates
        │           └── index.html
        └── test
            └── java
                └── hello
                    └── ControllerTest.java
    

    ...the user is greeted just fine with "Hello World!" at http://localhost:8080/, but the wiring of Spring's "context" does not seem to apply within the integration test (ControllerTest.java):

    java.lang.AssertionError: Status 
    Expected :200
    Actual   :404
    

    What is wrong with the project layout, and/or the configuration annotations in the test?

    src/main/webapp/ is intentionally missing, along with things like web.xml and WEB-INF/. The goal here is to use minimal configuration, with an integration test to test-drive the development of the view and controller of the application.

    Gory details below. Sorry in advance for the "wall of text."


    pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.1.RELEASE</version>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>
    

    Application.java

    package hello;
    
    // ...
    
    @SpringBootApplication
    public class Application {
    
      public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
      }
    }
    

    Controller.java

    package hello;
    
    @org.springframework.stereotype.Controller
    public class Controller {
    }
    

    Config.java

    package hello;
    
    // ...
    
    @Configuration
    public class Config extends WebMvcConfigurerAdapter {
    
      @Override
      public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
      }
    }
    

    ControllerTest.java

    package hello;
    
    // ...
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @ContextConfiguration(classes = Config.class)
    public class ControllerTest {
    
      @Autowired
      private WebApplicationContext wac;
    
      private MockMvc mockMvc;
    
      @Before
      public void setup() {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
      }
    
      @Test
      public void test() throws Exception {
        this.mockMvc
            .perform(get("/"))
            .andExpect(status().isOk());
      }
    }
    

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <title>Hello World!</title>
      </head>
      <body>
        <p>Hello world!</p>
      </body>
    </html>
    
  • Noumenon
    Noumenon about 7 years
    @SpringApplicationConfiguration is deprecated in favor of other things: stackoverflow.com/questions/39417530/…
  • user2758406
    user2758406 over 6 years
    This loads entire context of application to be used in TestClass
  • thevipulvats
    thevipulvats over 2 years
    I am facing same issue but i am using @SpringBootTest instead... Any idea how to resolve