Spring MockMvc WebApplicationContext is null when running JUnit Tests with Maven

15,043

you should add @SpringBootTest as an annotation before your test class. Like this:

@RunWith(SpringRunner.class)
@SpringBootTest
Share:
15,043
Ayub Malik
Author by

Ayub Malik

Updated on June 17, 2022

Comments

  • Ayub Malik
    Ayub Malik almost 2 years

    I have a Spring mock-mvc JUnit test class that contains two tests. When I run the tests within Eclipse IDE both tests pass (I use Eclipse Maven plugin).

    When running the tests from the command line using

    mvn test
    

    one of the tests fails because the WebApplicationContext that is @Autowired is sometimes null.

    Here is my test class

    @WebAppConfiguration
    @ActiveProfiles({ "dev", "test" })
    public class AddLinkEndpointMvcTest extends BaseMvc {
    
        @Autowired
        private WebApplicationContext wac;
    
        private MockMvc mockMvc;
    
        @Before
        public void before() {
            System.out.println("WAC = " + wac);
            mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        }
    
        @Test
        public void addLinkDoesNotSupportGet() throws Exception {
            mockMvc.perform(get("/myurl")).andExpect(status().is(HttpStatus.SC_METHOD_NOT_ALLOWED));
        }
    
        @Test
        public void addLinkBadRequestNoLinkAddress() throws Exception {
            mockMvc.perform(post("/myurl")).andExpect(status().is(HttpStatus.SC_BAD_REQUEST));
        }
    }
    

    Here is the BaseMvc class

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class BaseMvc {
    
        @Configuration
        @ComponentScan(basePackages = { "com.example.a", "com.example.b" })
        @Profile("test")
        public static class TestConfig {
    
            static {
                System.out.println("TEST CONFIG");
            }
    
            // ...some beans defined here
    
            @Bean
            public static PropertySourcesPlaceholderConfigurer properties() {
                PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
                configurer.setIgnoreUnresolvablePlaceholders(false);
                configurer.setLocations(new Resource[] { new ClassPathResource("sample-webapp.properties"),
                    new ClassPathResource("sample-domain.properties") });
                return configurer;
            }
    
        }
    
    }
    

    I have added the println calls to aide debugging. When running mvn test here is the relevant console output:

    WAC = null
    WAC = org.springframework.web.context.support.GenericWebApplicationContext@38795184: startup date [Thu Sep 19 16:24:22 BST 2013]; root of context hierarchy
    

    and the error

    java.lang.IllegalArgumentException: WebApplicationContext is required
            at org.springframework.util.Assert.notNull(Assert.java:112)
            at org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder.<init>(DefaultMockMvcBuilder.java:66)
            at org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup(MockMvcBuilders.java:46)
            at com.mypackage.AddLinkEndpointMvcTest.before(AddLinkEndpointMvcTest.java:31)
    

    So this is the problem line in the test

    @Autowired
    private WebApplicationContext wac;  
    

    Sometimes wac is null or has not completed initialisation before the JUnit @Before kicks in.

    What I don't understand is the WebApplicationContext is sometimes null and why it passes in Eclipse IDE!

    • Sotirios Delimanolis
      Sotirios Delimanolis over 10 years
      I'm unable to reproduce your error. Are you sure that's the class involved?
    • Mike Rylander
      Mike Rylander over 10 years
      Have you tried using constructor injection instead of field injection? This should force your WebApplicationContext to be initialized before AddLinkEndpointMvcTest is used.
    • Ayub Malik
      Ayub Malik over 10 years
      @Sotiros Yes tried again today after a while and still same issue
    • dehasi
      dehasi over 5 years
      Could you try @RunWith(SpringRunner.class) runner?
  • Ayub Malik
    Ayub Malik over 10 years
    JUnit needs a default constructor so wont let me get away with that