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.
MockMVC class is part of Spring MVC test framework which helps in testing the controllers explicitly starting a Servlet container. In this MockMVC tutorial, we will use it along with Spring boot's WebMvcTest class to execute Junit testcases which tests REST controller methods written for Spring boot 2 hateoas example.
From a technical point of view MockMvc is not thread-safe and shouldn't be reused. These setters are package private and a MockMvc instance can be acquired only through MockMvcBuilders . Hence you can't manipulte a MockMvc instance afterwards so that it is actually resuable across multiple tests.
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).
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With