中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

springboot~3.x項(xiang)目中使用集成(cheng)測試

在 Spring Boot 3.x 中為控制器編寫集成測試,主要是通過 @SpringBootTest 注解加載完整的應用上下文,并利用 MockMvcTestRestTemplate 來(lai)模擬 HTTP 請求并驗證響(xiang)應。下面(mian)我(wo)將為你提供一(yi)個清晰的(de)指南和代碼示例。

兩種測試

在(zai)Spring Boot項目中,測(ce)試(shi)(shi)通常分(fen)為單元測(ce)試(shi)(shi)和集成測(ce)試(shi)(shi)。以(yi)下是(shi)區分(fen)這兩種測(ce)試(shi)(shi)的一些指導原則:

單元測試

  • 定義:單元測試主要用于測試代碼中的單個“單元”,通常是一個方法或類。它們的目標是驗證特定功能的正確性。
  • 特征
    • 獨立性:單元測試不依賴于外部系統(如數據庫、網絡等)。
    • 快速執行:通常執行時間很短。
    • 使用Mock:通常會使用Mock對象來替代依賴項,以便只測試目標單元。
  • 示例
    @SpringBootTest
    public class UserServiceTest {
        
        @Mock
        private UserRepository userRepository;
    
        @InjectMocks
        private UserService userService;
    
        @Test
        public void testGetUserById() {
            // Arrange
            User user = new User(1, "John Doe");
            when(userRepository.findById(1)).thenReturn(Optional.of(user));
            
            // Act
            User result = userService.getUserById(1);
            
            // Assert
            assertEquals("John Doe", result.getName());
        }
    }
    

集成測試

  • 定義:集成測試用于測試多個組件之間的交互,通常是測試整個應用程序或其部分的行為。
  • 特征
    • 依賴性:集成測試通常會啟動Spring上下文,并可能連接到數據庫或其他外部服務。
    • 較慢執行:由于涉及多個組件,執行時間通常較長。
    • 真實環境:測試在接近真實環境的條件下運行。
  • 示例
    @SpringBootTest
    @AutoConfigureMockMvc
    public class UserControllerTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @Test
        public void testGetUser() throws Exception {
            mockMvc.perform(get("/users/1"))
                   .andExpect(status().isOk())
                   .andExpect(jsonPath("$.name").value("John Doe"));
        }
    }
    

如何區分

  1. 測試目標

    • 單元測試:關注單個類或方法。
    • 集成測試:關注多個組件的協作。
  2. 使用的工具

    • 單元測試:Mockito、JUnit等。
    • 集成測試:Spring Test、MockMvc等。
  3. 項目結構

    • 可以在src/test/java目錄中創建不同的包,例如unitintegration,分別存放單元測試和集成測試。
  4. 命名約定

    • 可以在文件名中添加前綴或后綴,例如UserServiceTest(單元測試)和UserControllerIntegrationTest(集成測試)。

?? Spring Boot 3.x 控制器集成測試指南

?? 1. 添加測試依賴

確保你的 pom.xml 中包含 Spring Boot Test starter 依賴,它通常已經(jing)包含了 JUnit Jupiter、Mockito、AssertJ 等測試所需的庫。

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

?? 2. 創建控制器

假設你有一個簡單的 REST 控制器 ExampleController

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class ExampleController {

    @GetMapping("/greet")
    public String greet(@RequestParam(required = false, defaultValue = "World") String name) {
        return "Hello, " + name + "!";
    }

    @PostMapping("/users")
    public User createUser(@RequestBody User user) {
        // 假設這是一個創建用戶并返回創建后信息的服務
        return userService.save(user); // userService 需要通過依賴注入
    }
}

?? 3. 編寫集成測試類

創建一個集成測試類,使用 @SpringBootTest@AutoConfigureMockMvc 來配置測試環境。

3.1 使用 MockMvc (模擬 MVC 環境)

這種方法不會啟(qi)動真正的服務器(qi),而是模擬 Servlet 環(huan)境,測(ce)試速度較快。

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.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import com.fasterxml.jackson.databind.ObjectMapper;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

// 使用 @SpringBootTest 加載完整的應用程序上下文
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK) // WebEnvironment.MOCK 是默認值,可省略
@AutoConfigureMockMvc // 自動配置 MockMvc
public class ExampleControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper; // Jackson 庫的 ObjectMapper,用于對象與 JSON 轉換

    @Test
    public void testGreetEndpoint() throws Exception {
        mockMvc.perform(get("/api/greet") // 發起 GET 請求
                .param("name", "Spring")) // 添加請求參數
                .andExpect(status().isOk()) // 斷言狀態碼為 200
                .andExpect(content().string("Hello, Spring!")); // 斷言響應內容
    }

    @Test
    public void testGreetEndpointWithDefault() throws Exception {
        mockMvc.perform(get("/api/greet"))
                .andExpect(status().isOk())
                .andExpect(content().string("Hello, World!"));
    }

    @Test
    public void testCreateUser() throws Exception {
        User newUser = new User("Alice", "alice@example.com");
        // 將 User 對象轉換為 JSON 字符串
        String userJson = objectMapper.writeValueAsString(newUser);

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON) // 設置請求內容類型
                .content(userJson)) // 設置請求體 JSON 內容
                .andExpect(status().isCreated()) // 斷言狀態碼為 201(假設創建成功返回 201)
                .andExpect(jsonPath("$.name").value("Alice")) // 使用 JsonPath 斷言返回的 JSON 字段值
                .andExpect(jsonPath("$.email").value("alice@example.com"));
    }
}

3.2 使用 TestRestTemplate (啟動真實服務器)

這種方法會啟動一個嵌入式的真實服(fu)務器(如 Tomcat),測(ce)試更(geng)接近于生產環境。

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.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

// 使用 RANDOM_PORT 啟動一個嵌入式服務器并監聽隨機端口,避免端口沖突
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleControllerWithServerTest {

    @Autowired
    private TestRestTemplate restTemplate; // 注入 TestRestTemplate

    @Test
    public void testGreetEndpoint() {
        // 使用 TestRestTemplate 發起請求
        ResponseEntity<String> response = restTemplate.getForEntity("/api/greet?name=Spring", String.class);
        
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isEqualTo("Hello, Spring!");
    }

    // 也可以測試 POST 請求
    @Test
    public void testCreateUser() {
        User newUser = new User("Bob", "bob@example.com");
        ResponseEntity<User> response = restTemplate.postForEntity("/api/users", newUser, User.class);
        
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
        assertThat(response.getBody()).isNotNull();
        assertThat(response.getBody().getName()).isEqualTo("Bob");
        assertThat(response.getBody().getEmail()).isEqualTo("bob@example.com");
    }
}

?? 4. 關鍵注解和配置說明

下表(biao)總結了(le)集成(cheng)測試(shi)中(zhong)常用的注解(jie)及其用途:

注解 說明 適用場景
@SpringBootTest 加載完整的 Spring 應用程序上下文,用于集成測試。 所有類型的集成測試
webEnvironment = WebEnvironment.MOCK 默認值。提供模擬的 Servlet 環境,不啟動真實服務器。依賴 @AutoConfigureMockMvc 使用 MockMvc 進行控制層測試,速度較快
webEnvironment = WebEnvironment.RANDOM_PORT 啟動嵌入式服務器并監聽隨機端口 使用 TestRestTemplateWebTestClient 進行測試
webEnvironment = WebEnvironment.DEFINED_PORT 使用 application.properties 中定義的端口(或默認的 8080)啟動服務器。 需要固定端口的測試場景
@AutoConfigureMockMvc 自動配置 MockMvc 實例,用于模擬 MVC 請求。通常與 WebEnvironment.MOCK 結合使用。 使用 MockMvc 進行測試時必需
@Test JUnit Jupiter 注解,標記一個方法為測試方法。 所有測試方法
@Import 顯式導入特定的配置類,用于測試。 需要覆蓋特定配置或引入測試專用配置時

?? 5. 處理依賴和模擬(Mocking)

在集成測試中,你通常希望測試完整的集成鏈,因此應盡量避免模擬(Mocking)。但如果某些外部依賴(如數據庫、第三方服務)無法在測試環境中使用,或者你想隔離測試特定層,Spring Boot 提供了 @MockBean 注(zhu)解來模擬 Bean。

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.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import com.example.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@SpringBootTest
@AutoConfigureMockMvc
public class ExampleControllerWithMockServiceTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @MockBean // 模擬 UserService 這個 Bean,真實的 UserService 不會被調用
    private UserService userService;

    @Test
    public void testCreateUserWithMockService() throws Exception {
        User inputUser = new User("Charlie", "charlie@example.com");
        User savedUser = new User(1L, "Charlie", "charlie@example.com"); // 假設保存后有了 ID

        // 模擬 userService.save() 方法的行為
        when(userService.save(any(User.class))).thenReturn(savedUser);

        mockMvc.perform(post("/api/users")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(inputUser)))
                .andExpect(status().isCreated())
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.name").value("Charlie"))
                .andExpect(jsonPath("$.email").value("charlie@example.com"));
    }
}

?? 6. 運行測試

你可以使(shi)用(yong) IDE 中(zhong)的運(yun)行測(ce)試(shi)功能,或者通(tong)過 Maven 命(ming)令運(yun)行測(ce)試(shi):

mvn test

Maven 會在 src/test/java 目錄下查找測試類并運行。

?? 核心要點

  • 集成測試 (Integration Test):使用 @SpringBootTest 加載完整的應用程序上下文,測試各個組件之間的集成情況。
  • MockMvc:適用于模擬 MVC 環境的測試,無需啟動真實服務器,速度快。 使用 perform 發起請求,andExpect 進行斷言。
  • TestRestTemplate:適用于啟動真實嵌入式服務器的測試,更接近真實環境。 直接發起 HTTP 請求并接收響應。
  • 隨機端口:使用 WebEnvironment.RANDOM_PORT 可以避免測試時的端口沖突問題。
  • @MockBean:當你需要模擬應用程序上下文中的某個 Bean 時(例如模擬一個不易在測試環境中構建的外部服務),可以使用此注解。

希望這個指南(nan)能(neng)幫助你在 Spring Boot 3.x 中順(shun)利編寫控制器的(de)集成(cheng)測試!

posted @ 2025-08-26 17:09  張占嶺  閱讀(184)  評論(0)    收藏  舉報