如何为Spring Boot Controller端点编写单元测试

use*_*723 68 java junit unit-testing spring-test-mvc spring-boot

我有一个示例Spring Boot应用程序,其中包含以下内容

启动主类

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
Run Code Online (Sandbox Code Playgroud)

调节器

@RestController
@EnableAutoConfiguration
public class HelloWorld {
    @RequestMapping("/")
    String gethelloWorld() {
        return "Hello World!";
    }

}
Run Code Online (Sandbox Code Playgroud)

为控制器编写单元测试最简单的方法是什么?我尝试了以下但它抱怨无法自动装载WebApplicationContext

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
public class DemoApplicationTests {

    final String BASE_URL = "http://localhost:8080/";

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void testSayHelloWorld() throws Exception{

         this.mockMvc.perform(get("/")
                 .accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
                 .andExpect(status().isOk())
                 .andExpect(content().contentType("application/json"));
    }

    @Test
    public void contextLoads() {
    }

}
Run Code Online (Sandbox Code Playgroud)

Mas*_*ave 46

Spring MVC提供了一个独立设置,支持测试相对简单的控制器,无需上下文.

通过注册一个或多个@Controller的实例并以编程方式配置Spring MVC基础结构来构建MockMvc.这允许完全控制控制器的实例化和初始化及其依赖性,类似于普通单元测试,同时还可以一次测试一个控制器.

控制器的示例测试可以很简单

public class DemoApplicationTests {

    private MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = standaloneSetup(new HelloWorld()).build();
    }

    @Test
    public void testSayHelloWorld() throws Exception {
        this.mockMvc.perform(get("/")
           .accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
           .andExpect(status().isOk())
           .andExpect(content().contentType("application/json"));

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您需要上面的示例代码的一些静态导入.对于`content()`,它将是`org.springframework.test.web.servlet.result.MockMvcResultMatchers.content`.顺便说一下:我建议使用MediaType常量,如`MediaType.APPLICATION_JSON`和`MediaType.APPLICATION_JSON_UTF8`,而不是示例中使用的基于字符串的值. (4认同)

geo*_*and 28

Spring Boot中推出的新测试改进1.4.M2可以帮助减少编写这些情况所需的代码量.

测试看起来像这样:

import static org.springframework.test.web.servlet.request.MockMvcRequestB??uilders.get; 
import static org.springframework.test.web.servlet.result.MockMvcResultMat??chers.content; 
import static org.springframework.test.web.servlet.result.MockMvcResultMat??chers.status;

    @RunWith(SpringRunner.class)
    @WebMvcTest(HelloWorld.class)
    public class UserVehicleControllerTests {

        @Autowired
        private MockMvc mockMvc;

        @Test
        public void testSayHelloWorld() throws Exception {
            this.mockMvc.perform(get("/").accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
                    .andExpect(status().isOk())
                    .andExpect(content().contentType("application/json"));

        }

    }
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息和文档,请参阅博客文章

  • 这不起作用.你仍然会得到一个``java.lang.IllegalStateException:无法找到@SpringBootConfiguration,你需要使用@ContextConfiguration或@SpringBootTest(classes = ...)和你的test``错误. (7认同)
  • 很高兴添加静态导入:import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; (3认同)

小智 6

这是使用Spring MVC的standaloneSetup的另一个答案.使用这种方式,您可以自动装配控制器类或模拟它.

    import static org.mockito.Mockito.mock;
    import static org.springframework.test.web.server.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.server.result.MockMvcResultMatchers.content;
    import static org.springframework.test.web.server.result.MockMvcResultMatchers.status;

    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.http.MediaType;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.web.server.MockMvc;
    import org.springframework.test.web.server.setup.MockMvcBuilders;


    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class DemoApplicationTests {

        final String BASE_URL = "http://localhost:8080/";

        @Autowired
        private HelloWorld controllerToTest;

        private MockMvc mockMvc;

        @Before
        public void setup() {
            this.mockMvc = MockMvcBuilders.standaloneSetup(controllerToTest).build();
        }

        @Test
        public void testSayHelloWorld() throws Exception{
            //Mocking Controller
            controllerToTest = mock(HelloWorld.class);

             this.mockMvc.perform(get("/")
                     .accept(MediaType.parseMediaType("application/json;charset=UTF-8")))
                     .andExpect(status().isOk())
                     .andExpect(content().mimeType(MediaType.APPLICATION_JSON));
        }

        @Test
        public void contextLoads() {
        }

    }
Run Code Online (Sandbox Code Playgroud)


Cha*_*ang 5

@WebAppConfiguration( org.springframework.test.context.web.WebAppConfiguration) 注释添加到您的 DemoApplicationTests 类将起作用。