Spring Boot MVC 测试 - MockMvc 始终为空

Posted

技术标签:

【中文标题】Spring Boot MVC 测试 - MockMvc 始终为空【英文标题】:Spring Boot MVC Test - MockMvc is always null 【发布时间】:2020-04-19 09:37:48 【问题描述】:

我正在尝试编写我的第一个 Spring MVC 测试,但我无法让 Spring Boot 将 MockMvc 依赖项注入我的测试类。这是我的课:

@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());
  


我检查过 IntelliJ 的调试器,可以确认 mockMvc 本身为空。因此,所有异常消息告诉我的是“java.lang.NullPointerException”。

我已经尝试为“@SpringBootTest”或“@RunWith(SpringRunner.class)”等测试类添加更通用的 Spring Boot 注释,以防它与初始化 Spring 有关但没有运气。

【问题讨论】:

你能提供你的 pom 或 gradle 文件吗? 【参考方案1】:

奇怪,前提是你也尝试过 @RunWith(SpringRunner.class)@SpringBootTest。您是否也尝试过 @AutoConfigureMockMvc 注释?下面的示例运行良好。

@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")));
    

完整示例here

关于@WebMvcTest 和@AutoConfigureMockMvc 注释的使用,可能还值得考虑以下cmets,详见Spring's documentation

默认情况下,使用 @WebMvcTest 注解的测试也会自动配置 Spring Security 和 MockMvc(包括对 htmlUnit WebClient 和 Selenium WebDriver 的支持)。要对 MockMVC 进行更细粒度的控制,可以使用 @AutoConfigureMockMvc 注解。

通常@WebMvcTest 与@MockBean 或@Import 结合使用以创建@Controller bean 所需的任何协作者。

如果您希望加载完整的应用程序配置并使用 MockMVC,则应考虑将 @SpringBootTest 与 @AutoConfigureMockMvc 结合使用,而不是使用此注解。

使用 JUnit 4 时,此注解应与 @RunWith(SpringRunner.class) 结合使用。

【讨论】:

@ElDuderino,很高兴它做到了。编码愉快! 非常感谢,这成功了,让我通过了 NullPointerException。我现在使用这些注释: @RunWith(SpringRunner.class) @SpringBootTest(classes = MyApplication.class) @AutoConfigureMockMvc @PropertySource("classpath:application.properties") 不幸的是,测试现在卡在 Spring-logo 上。当我运行应用程序并手动发布我的文件时,它工作正常。可能需要补充一点,这个测试基本上覆盖了应用的每一层,所以Spring Boot需要初始化几乎整个应用才能运行测试。 好的,不知道你的 byte[] 内容是否与 MediaType.APPLICATION_JSON 兼容?您可以将 json 文件内容(作为纯文本)放在一个字符串中并将其用作内容而不是您的 byte[]...如果它通过了卡住,那么我们知道它是否是格式问题 不是这样,我忘了声明要与@ActiveProfiles 一起使用的配置文件(我有多个application.properties)。现在它开始了。感谢您的帮助,由于原始问题现已解决,因此我将您的答案标记为已接受。 @ElDuderino 完美。很高兴一切都解决了。编码快乐,2020 年新年快乐【参考方案2】:

我遇到了同样的问题。原来MockMvc没有被注入是因为不兼容的@Test注解。导入的是 org.junit.Test,但将其更改为 org.junit.jupiter.api.Test 解决了问题。

【讨论】:

【参考方案3】:

接受的答案有效,但我也解决了这个问题,但没有导入 @RunWith(SpringRunner.class)

在我的例子中,我导入了 org.junit.Test 而不是更新的 org.junit.jupiter.api.Test

如果您使用的是 Maven,则可以避免犯此错误,从 spring-boot-starter-test 依赖项中排除 junit-vintage-engine

<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>

【讨论】:

以上是关于Spring Boot MVC 测试 - MockMvc 始终为空的主要内容,如果未能解决你的问题,请参考以下文章

高手都这么给 Spring MVC 做单元测试!

spring-boot-starter-test

高手如何给 Spring MVC 做单元测试?

如何在 Junit5 / spring boot 中命令执行控制器测试类?

如何使用 power mock 对 Spring Boot Rest 控制器和异常处理程序进行单元测试

springboot利用mock进行junit单元测试,测试controller