27

I'm trying to write my first Spring MVC test but I just cannot get Spring Boot to inject the MockMvc dependency into my test class. Here is my class:

@WebMvcTest
public class WhyWontThisWorkTest {

  private static final String myUri = "uri";
  private static final String jsonFileName = "myRequestBody.json";

  @Autowired
  private MockMvc mockMvc;

  @Test
  public void iMustBeMissingSomething() throws Exception {
    byte[] jsonFile = Files.readAllBytes(Paths.get("src/test/resources/" + jsonFileName));
    mockMvc.perform(
        MockMvcRequestBuilders.post(myUri)
            .content(jsonFile)
            .contentType(MediaType.APPLICATION_JSON))
        .andExpect(MockMvcResultMatchers.status().is2xxSuccessful());
  }
}

I've checked with IntelliJ's debugger and can confirm that mockMvc itself is null. Thus, all the Exception message tells me is "java.lang.NullPointerException".

I've already tried adding more general Spring Boot annotations for test classes like "@SpringBootTest" or "@RunWith(SpringRunner.class)" in case it has something to do with initializing Spring but no luck.

ElDuderino
  • 275
  • 1
  • 3
  • 6

4 Answers4

32

Strange, provided that you have also tried with @RunWith(SpringRunner.class) and @SpringBootTest. Have you also tried with the @AutoConfigureMockMvc annotation? The sample below is working fine.

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void getHello() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(content().string(equalTo("Hello World of Spring Boot")));
    }
}

complete sample here

It may also be worthwhile to consider the following comments regarding the usage of the @WebMvcTest and @AutoConfigureMockMvc annotations as detailed in Spring's documentation

By default, tests annotated with @WebMvcTest will also auto-configure Spring Security and MockMvc (include support for HtmlUnit WebClient and Selenium WebDriver). For more fine-grained control of MockMVC the @AutoConfigureMockMvc annotation can be used.

Typically @WebMvcTest is used in combination with @MockBean or @Import to create any collaborators required by your @Controller beans.

If you are looking to load your full application configuration and use MockMVC, you should consider @SpringBootTest combined with @AutoConfigureMockMvc rather than this annotation.

When using JUnit 4, this annotation should be used in combination with @RunWith(SpringRunner.class).

Community
  • 1
  • 1
alainlompo
  • 4,414
  • 4
  • 32
  • 41
  • @ElDuderino, glad it did. Happy coding! – alainlompo Jan 01 '20 at 22:48
  • Thanks a lot, that did the trick and got me past the NullPointerException. I now use these annotations: @RunWith(SpringRunner.class) @SpringBootTest(classes = MyApplication.class) @AutoConfigureMockMvc @PropertySource("classpath:application.properties") Unfortunately, the test is now stuck at the Spring-logo. When I run the application and post my files manually it works fine. I might need to add that this test basically covers every layer of the application, so Spring Boot needs to initialize almost the entire application to run the test. – ElDuderino Jan 01 '20 at 22:55
  • Ok, I wonder if your byte[] content is compatible with MediaType.APPLICATION_JSON? Can you place the json file content (as plain text) in a string and use it as content instead of your byte[]...If it passes the stuck then we know if it was a format issue – alainlompo Jan 01 '20 at 23:13
  • That wasn't it, I forgot to declare which profile I want to use with @ActiveProfiles (I have more than one application.properties). Now it starts. Thanks for your help, I marked your answer as accepted since the original problem is solved now. – ElDuderino Jan 02 '20 at 13:35
  • 2
    @ElDuderino perfect. Glad all is solved. Happy coding, and happy new year 2020 – alainlompo Jan 02 '20 at 13:53
  • Very similar setup, I added `@AutoConfigureMockMvc` it didnt help. The example I had was Autowiring `WebApplicationContext` but not `MockMvc`, I added the `@Autowired` for `private MockMvc mockMvc;` and everything worked, thank you! – JGlass Jan 09 '23 at 20:02
26

I faced the same issue. It turned out that MockMvc was not injected due to incompatible @Test annotation. The import was org.junit.Test, but changing it to org.junit.jupiter.api.Test solved the issue.

Newbie
  • 4,462
  • 11
  • 23
Maksym Kosenko
  • 515
  • 7
  • 12
7

Accepted answer works, however I solved the issue also without importing @RunWith(SpringRunner.class).

In my case I had imported org.junit.Test instead of the newer org.junit.jupiter.api.Test.

If you are using Maven you can avoid to make this mistake excluding junit-vintage-engine from spring-boot-starter-test dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>
xonya
  • 2,146
  • 29
  • 37
0

check if you have the latest or at least updated maven-surefire-plugin. It helped me to solve the issue

Serhii Povísenko
  • 3,352
  • 1
  • 30
  • 48