Spring Boot 中的单元测试

Posted

技术标签:

【中文标题】Spring Boot 中的单元测试【英文标题】:Unit testing in spring boot 【发布时间】:2017-02-08 14:21:20 【问题描述】:

我对 Spring Boot 很陌生,正在尝试学习如何在 Spring Boot 中进行测试。我阅读了有助于集成测试应用程序的 @SpringBootTest 注释。我想知道在 Spring Boot 中应该如何进行单元测试。单元测试是否需要指定 @SpringBootTest 注释,还是仅用于集成测试?是否有特定的注释可用于单元测试?

任何指针将不胜感激。提前致谢!

编辑: SpringBootTest 注解是否只用于集成测试?我在 Spring 文档中找到了以下代码示例:

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

@Autowired
private MockMvc mvc;

@Test
public void getHello() throws Exception 
    mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().string(equalTo("Greetings from Spring Boot!")));


这是单元测试还是集成测试?我的猜测是它不是集成测试,因为它使用了 MockMvc。那正确吗?如果是这样,这是否意味着 @SpringBootTest 注解可以用于不是完全成熟的集成测试的测试?

【问题讨论】:

你不需要任何特别的东西来进行单元测试。只需使用 new 创建您的待测组件。 正如@JBNizet 所说,在 Spring Boot 应用程序中对类进行单元测试不需要任何特殊的东西。只需按照不使用 Spring Boot 的方式编写和运行测试类即可。 但是,如果您想知道如何对端点的 HTTP 调用进行测试(这将是集成测试,而不是单元测试),我可以提供帮助;就在你的帖子里这么说吧。 感谢您的回复,我知道 Spring Boot 提供了非常先进的集成测试功能。我知道 Spring Boot 提供了一个切片测试功能,可以测试应用程序的各个组件。例如。 WebMvcTest 注解可用于测试控制器部分。这可以被认为是单元测试吗? 另外,我知道需要将“spring-boot-starter-test”依赖添加到pom文件中以添加测试支持。这种依赖有什么作用?这应该只用于集成测试吗? 【参考方案1】:

这就是我要做的: 对于端到端集成测试:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ApplicationTests 

    @Autowired
    private TestRestTemplate restTemplate;
    @Autowired
    private CarRepository repository;
    @Autowired
    private CarService carService;

    @Test
    public void contextLoads() 
    

    @Test
    public void basicTest() 
        String body = this.restTemplate.getForObject("/", String.class);
        assertThat(body).contains("Not Found");
    

仅用于测试控制器(控制器单元测试):

    @RunWith(SpringRunner.class)
    @WebMvcTest(controllers = CarController.class, excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
    public class ControllerTests 

        @Autowired
        private MockMvc mvc;

        @MockBean
        private CarRepository carRepository;

        @MockBean
        private MongoTemplate mongoTemplatel;

        @Test
        public void testGet() throws Exception 
            short year = 2010;
            given(this.carRepository.findByVin("ABC"))
                    .willReturn(new Car("ABC", "Honda", "Accord", year, 100000, "Red", "Ex-V6"));
            this.mvc.perform(get("/car").param("VIN", "ABC").accept(MediaType.APPLICATION_JSON))
                    .andExpect(status().isOk()).andExpect(content().string("[\"vin\":\"ABC\",\"make\":\"Honda\",\"model\":\"Accord\",\"year\":2010,\"mileage\":100000,\"color\":\"Red\",\"trim\":\"Ex-V6\",\"type\":null,\"maintenanceTasksList\":[\"Oil Change\",\"Tire Rotation\"]]"));
        
    

您可以找到包含集成和单元测试的完整 Spring Boot 应用程序here。

【讨论】:

【参考方案2】:

严格来说,“单元”测试不应该使用 Spring。只需像往常一样使用 JUnit/TestNG/Spock/whatever 来测试各个类。 @SpringBootTest 用于集成及其他测试。

【讨论】:

以上是关于Spring Boot 中的单元测试的主要内容,如果未能解决你的问题,请参考以下文章

单元测试中的 Spring Boot 数据源

Spring-Boot 单元测试:ConstraintValidator 中的@Value

Spring Boot 单元测试,保姆级教程!

kotlin + Spring boot 中的单元测试休息控制器

java 裸机单元测试Spring Boot应用程序中的RestController方法。

spring-boot 单元测试获取应用程序属性