返回介绍

10.1 Spring Boot 测试

发布于 2025-04-21 20:58:46 字数 8415 浏览 0 评论 0 收藏

Spring Boot 提供了许多公用方法与注解,可以帮助开发者测试应用程序。Spring Boot 主要包括 spring-boot-test 与 spring-boot-test-autoconfigure 核心模块。Spring Boot 提供了 spring-boot-starter-test 的 Starter,主要集成了 JUnit Jupiter、AssertJ 和 Hamcrest 等常用测试框架。

10.1.1 Spring Boot 测试简介

在 Spring Boot Test 诞生之前,常用的测试框架是 JUnit 等。Spring Boot Test 诞生后,集成了上述测试框架。Spring 框架的一个主要优势是更容易集成单元测试,可以通过 new 操作符直接生成实例,或者用 mock 对象代替真实的依赖。通常,测试不只是单元测试,还有集成测试,Spring Boot Test 可以在不部署应用程序的前提下进行集成测试。

使用 Spring Boot Test,需要在项目中增加 spring-boot-starter-test 的 Starter 依赖,具体如下:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
</dependency>

使用 @SpringBootTest 注解,即可进行测试。

如果项目中依赖 spring-boot-starter-test,则自动添加以下类库。

  • JUnit 5:标准的测试框架。
  • Spring Test 与 Spring Boot Test:集成测试与公共类。
  • AssertJ:断言库。
  • Hamcrest:matcher 库。
  • Mockito:mock 库。
  • JSONassert:为 JSON 提供断言功能。
  • JsonPath:为 JSON 提供 XPath 功能。

通常情况下,Spring Boot Test 支持的测试种类可以分为以下 3 种:

  • 单元测试:主要用于测试类功能等。
  • 切片测试:介于单元测试与集成测试之间,在特定环境下才能执行。
  • 集成测试:测试一个完整的功能逻辑。

10.1.2 核心注解

为了避免复杂的配置,Spring 引入了大量的注解方式进行测试,这样可以减轻很多工作量。让读者理解并学会使用这些注解是本节学习的主要目标,了解这些注解,可以帮助读者更加容易地掌握 Spring Boot Test 的整个框架。

1. @SpringBootTest 注解

Spring Boot 用 @SpringBootTest 注解替代了 spring-test 中的 @ContextConfiguration 注解,该注解可以创建 ApplicationContext,而且还添加了一些其他注解来测试特定的应用。使用 @SpringBootTest 的 WebEnvironment 属性来修改测试的运行方式。

  • MOCK:加载 Web 应用程序上下文并提供模拟的 Web 环境。该注解不会启动嵌入的服务器,可以结合 @AutoConfigureMockMvc 和 @AutoConfigureWebTest-Client 注解使用。
  • RANDOM_PORT:加载 WebServerApplicationContext 并提供真实的 Web 环境,嵌入的服务器启动后可以监听随机端口。
  • DEFINED_PORT:加载 WebServerApplicationContext 并提供真实的 Web 环境,嵌入的服务器启动后可以监听特定的端口。特定的端口可以从 application.properties 获取,也可以设置为默认的 8080 端口。
  • NONE:使用 SpringApplication 加载 ApplicationContext,但不提供任何 Web 环境。

示例代码如下:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.Web
Environment;
import org.springframework.boot.test.web.client.TestRestTemplate;

import static org.assertj.core.api.Assertions.assertThat;
//定义测试类
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RandomPortTestRestTemplateExampleTests {

    @Test
    void exampleTest(@Autowired TestRestTemplate restTemplate) {
        String body = restTemplate.getForObject("/", String.class);
        assertThat(body).isEqualTo("Hello World");      //返回结果断言
    }
}

2. @RunWith 注解

Spring Boot Test 默认使用 JUnit 5 框架,@RunWith(SpringRunner.class) 注解可方便开发者使用 JUnit 4 框架。使用方式如下:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.
RANDOM_PORT)
class DemoApplicationTests { ... }

3. @WebMvcTest 注解

如果要测试 Spring MVC controllers 是否按预期那样工作,则用 @WebMvcTest 注解。@WebMvcTest 注解可自动配置 Spring MVC,并会限制扫描 @Controller 和 @ControllerAdvice 等注解的 Bean。

通常,@WebMvcTest 仅限于单个 Controller,并结合 @MockBean 注解提供对某个类的模拟实现。@WebMvcTest 还会自动配置 MockMvc。MockMvc 提供了一个强大的方法可以快速测试 MVC 控制器,并且无须启动一个完整的 HTTP 服务器。示例代码如下:

import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvc
RequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.*;

@WebMvcTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private MockMvc mvc;                                //注入 MockMvc

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        this.mvc.perform(get("/sboot/vehicle").accept(MediaType.
TEXT_PLAIN))
                .andExpect(status().isOk()).andExpect(content().
string("Honda Civic"));
    }
}

4. @WebFluxTest 注解

@DataJpaTest 注解可以测试 JPA 应用。默认情况下,该注解会扫描 @Entity 注解的类及 repositories 类。@DataJpaTest 注解不会扫描 @Component 和 @Configuration-Properties 注解的对象。示例代码如下:

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.orm.jpa.*;

import static org.assertj.core.api.Assertions.*;
//JPA 测试
@DataJpaTest
class ExampleRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    void testExample() throws Exception {
        this.entityManager.persist(new User("sboot", "1234"));
        User user = this.repository.findByUsername("sboot");
        assertThat(user.getUsername()).isEqualTo("sboot");
        //断言用户名
        assertThat(user.getVin()).isEqualTo("1234");
    }
}

5. @DataMongoTest 注解

@DataMongoTest 注解可以用来测试 MongoDB 程序。默认会配置一个嵌入的 MongoDB 并配置一个 MongoTemplate 对象,然后扫描 @Document 注解类。示例代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.Data
MongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;
//Mongo 测试
@DataMongoTest
class ExampleDataMongoTests {

    @Autowired
    private MongoTemplate mongoTemplate;
    ...
}

6. @DataRedisTest 注解

@DataRedisTest 注解用来测试 Redis 应用程序。示例代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.Data
RedisTest;
//Redis 测试
@DataRedisTest
class ExampleDataRedisTests {

    @Autowired
    private YourRepository repository;
    ...
}

7. @RestClientTest 注解

@RestClientTest 注解用来测试 REST clients。默认情况下会自动配置 Jackson、GSON、Jsonb、RestTemplateBuilder,以及对 MockRestServiceServer 的支持。示例代码如下:

@RestClientTest(RemoteVehicleDetailsService.class)
class ExampleRestClientTest {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
            throws Exception {
        this.server.expect(requestTo("/greet/details"))
                .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }
}

8. @AutoConfigureMockMvc 注解

@SpringBootTest 注解通常不会启动服务器,如果在测试中用 Web 端点进行测试,可以添加 MockMvc 配置。示例代码如下:

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.
AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvc
RequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvc
ResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class MockMvcExampleTests {

    @Test
    void exampleTest(@Autowired MockMvc mvc) throws Exception {
        mvc.perform(get("/")).andExpect(status().isOk()).andExpect
(content().string("Hello World"));
    }
}

9. @MockBean 注解

测试的过程中某些场景需要模拟一些组件,这时就需要使用 @MockBean 注解。示例代码如下:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@SpringBootTest
class MyTests {

    @MockBean
    private RemoteService remoteService;

    @Autowired
    private Reverser reverser;

    @Test
    void exampleTest() {
        given(this.remoteService.someCall()).willReturn("mock");
        String reverse = reverser.reverseSomeCall();
        assertThat(reverse).isEqualTo("kcom");
    }
}

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。