亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot測(cè)試之@SpringBootTest與MockMvc的實(shí)戰(zhàn)應(yīng)用小結(jié)

 更新時(shí)間:2025年03月11日 10:51:01   作者:程序媛學(xué)姐  
本文將深入探討SpringBoot測(cè)試中兩個(gè)核心工具:@SpringBootTest注解與MockMvc測(cè)試框架的實(shí)戰(zhàn)應(yīng)用,幫助開發(fā)者構(gòu)建更穩(wěn)健的測(cè)試體系,提高代碼質(zhì)量與可維護(hù)性,感興趣的朋友一起看看吧

引言

在現(xiàn)代企業(yè)級(jí)應(yīng)用開發(fā)中,測(cè)試已成為確保軟件質(zhì)量的關(guān)鍵環(huán)節(jié)。SpringBoot作為當(dāng)前最流行的Java開發(fā)框架,提供了完善的測(cè)試支持機(jī)制。本文將深入探討SpringBoot測(cè)試中兩個(gè)核心工具:@SpringBootTest注解與MockMvc測(cè)試框架的實(shí)戰(zhàn)應(yīng)用,幫助開發(fā)者構(gòu)建更穩(wěn)健的測(cè)試體系,提高代碼質(zhì)量與可維護(hù)性。

一、SpringBoot測(cè)試基礎(chǔ)

1.1 測(cè)試環(huán)境配置

SpringBoot提供了豐富的測(cè)試支持,使開發(fā)者能夠方便地進(jìn)行單元測(cè)試和集成測(cè)試。在SpringBoot項(xiàng)目中進(jìn)行測(cè)試需要引入spring-boot-starter-test依賴,該依賴包含JUnit、Spring Test、AssertJ等測(cè)試相關(guān)庫(kù)。測(cè)試環(huán)境的正確配置是高效測(cè)試的基礎(chǔ),確保測(cè)試用例能夠在與生產(chǎn)環(huán)境相似的條件下運(yùn)行,從而提高測(cè)試結(jié)果的可靠性。

// build.gradle配置
dependencies {
    // SpringBoot基礎(chǔ)依賴
    implementation 'org.springframework.boot:spring-boot-starter-web'
    // 測(cè)試相關(guān)依賴
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    // JUnit 5支持
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}
// 或者在Maven中的pom.xml配置
/*
<dependencies>
    <!-- SpringBoot基礎(chǔ)依賴 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 測(cè)試相關(guān)依賴 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
*/

1.2 測(cè)試目錄結(jié)構(gòu)

一個(gè)規(guī)范的測(cè)試目錄結(jié)構(gòu)有助于測(cè)試用例的組織和管理。在SpringBoot項(xiàng)目中,測(cè)試代碼通常位于src/test/java目錄下,測(cè)試資源文件位于src/test/resources目錄。測(cè)試類的包結(jié)構(gòu)應(yīng)與主代碼保持一致,便于關(guān)聯(lián)和維護(hù)。測(cè)試配置文件可以覆蓋主配置,為測(cè)試提供專用環(huán)境參數(shù)。

src
 ├── main
 │    ├── java
 │    │    └── com.example.demo
 │    │         ├── controller
 │    │         ├── service
 │    │         └── repository
 │    └── resources
 │         └── application.properties
 └── test
      ├── java
      │    └── com.example.demo
      │         ├── controller  // 控制器測(cè)試類
      │         ├── service     // 服務(wù)測(cè)試類
      │         └── repository  // 數(shù)據(jù)訪問測(cè)試類
      └── resources
           └── application-test.properties  // 測(cè)試專用配置

二、@SpringBootTest注解詳解

2.1 基本用法與配置選項(xiàng)

@SpringBootTest注解是SpringBoot測(cè)試的核心,它提供了加載完整應(yīng)用程序上下文的能力。通過(guò)這個(gè)注解,可以創(chuàng)建接近真實(shí)環(huán)境的測(cè)試環(huán)境,使集成測(cè)試更加可靠。@SpringBootTest支持多種配置選項(xiàng),可以根據(jù)測(cè)試需求進(jìn)行靈活調(diào)整,包括指定啟動(dòng)類、測(cè)試配置文件、Web環(huán)境類型等。

package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.env.Environment;
import static org.junit.jupiter.api.Assertions.assertNotNull;
// 基本用法:加載完整的Spring應(yīng)用上下文
@SpringBootTest
public class BasicApplicationTests {
    @Autowired
    private Environment environment;  // 注入環(huán)境變量
    @Test
    void contextLoads() {
        // 驗(yàn)證上下文是否正確加載
        assertNotNull(environment);
        System.out.println("Active profiles: " + String.join(", ", environment.getActiveProfiles()));
    }
}
// 高級(jí)配置:自定義測(cè)試屬性
@SpringBootTest(
    // 指定啟動(dòng)類
    classes = DemoApplication.class,
    // 指定Web環(huán)境類型
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    // 設(shè)置測(cè)試屬性
    properties = {
        "spring.profiles.active=test",
        "server.servlet.context-path=/api"
    }
)
class CustomizedApplicationTest {
    // 測(cè)試代碼...
}

2.2 不同WebEnvironment模式的應(yīng)用場(chǎng)景

@SpringBootTest注解的webEnvironment屬性定義了測(cè)試的Web環(huán)境類型,有四種可選值:MOCK、RANDOM_PORT、DEFINED_PORT和NONE。每種模式適用于不同的測(cè)試場(chǎng)景。正確選擇Web環(huán)境模式可以提高測(cè)試效率,減少資源消耗。

package com.example.demo;
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.boot.test.web.server.LocalServerPort;
import static org.assertj.core.api.Assertions.assertThat;
// MOCK模式:不啟動(dòng)服務(wù)器,適用于通過(guò)MockMvc測(cè)試控制器
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class MockWebEnvironmentTest {
    // 使用MockMvc測(cè)試...
}
// RANDOM_PORT模式:?jiǎn)?dòng)真實(shí)服務(wù)器,隨機(jī)端口,適用于端到端測(cè)試
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RandomPortWebEnvironmentTest {
    @LocalServerPort
    private int port;  // 獲取隨機(jī)分配的端口
    @Autowired
    private TestRestTemplate restTemplate;
    @Test
    void testHomeEndpoint() {
        // 發(fā)送真實(shí)HTTP請(qǐng)求
        String response = restTemplate.getForObject(
            "http://localhost:" + port + "/api/home", 
            String.class
        );
        assertThat(response).contains("Welcome");
    }
}
// DEFINED_PORT模式:使用application.properties中定義的端口
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class DefinedPortWebEnvironmentTest {
    // 使用固定端口測(cè)試...
}
// NONE模式:不啟動(dòng)Web環(huán)境,適用于純業(yè)務(wù)邏輯測(cè)試
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
class NoWebEnvironmentTest {
    // 僅測(cè)試服務(wù)層和存儲(chǔ)層...
}

三、MockMvc實(shí)戰(zhàn)應(yīng)用

3.1 MockMvc基本使用方法

MockMvc是Spring MVC測(cè)試框架的核心組件,它模擬HTTP請(qǐng)求和響應(yīng),無(wú)需啟動(dòng)真實(shí)服務(wù)器即可測(cè)試控制器。MockMvc提供了流暢的API,可以構(gòu)建請(qǐng)求、執(zhí)行調(diào)用、驗(yàn)證響應(yīng)。這種方式的測(cè)試執(zhí)行速度快,資源消耗少,特別適合控制器單元測(cè)試。使用MockMvc可以確保Web層代碼的正確性和穩(wěn)定性。

package com.example.demo.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
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;
// @WebMvcTest專注于測(cè)試控制器層,只加載MVC相關(guān)組件
@WebMvcTest(UserController.class)
public class UserControllerTest {
    @Autowired
    private MockMvc mockMvc;  // MockMvc由Spring自動(dòng)注入
    @Test
    void testGetUserById() throws Exception {
        // 執(zhí)行GET請(qǐng)求并驗(yàn)證響應(yīng)
        mockMvc.perform(get("/users/1"))  // 構(gòu)建GET請(qǐng)求
               .andExpect(status().isOk())  // 驗(yàn)證HTTP狀態(tài)碼為200
               .andExpect(content().contentType("application/json"))  // 驗(yàn)證內(nèi)容類型
               .andExpect(content().json("{\"id\":1,\"name\":\"John\"}"));  // 驗(yàn)證JSON響應(yīng)內(nèi)容
    }
}

3.2 高級(jí)請(qǐng)求構(gòu)建和響應(yīng)驗(yàn)證

MockMvc提供了豐富的請(qǐng)求構(gòu)建選項(xiàng)和響應(yīng)驗(yàn)證方法,可以全面測(cè)試控制器的各種行為。通過(guò)高級(jí)API,可以模擬復(fù)雜的請(qǐng)求場(chǎng)景,包括添加請(qǐng)求頭、設(shè)置參數(shù)、提交表單數(shù)據(jù)、上傳文件等。同時(shí),MockMvc還提供了詳細(xì)的響應(yīng)驗(yàn)證機(jī)制,可以檢查HTTP狀態(tài)碼、響應(yīng)頭、響應(yīng)體內(nèi)容等。

package com.example.demo.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import static org.hamcrest.Matchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(ProductController.class)
public class ProductControllerAdvancedTest {
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private ObjectMapper objectMapper;  // 用于JSON轉(zhuǎn)換
    @Test
    void testCreateProduct() throws Exception {
        // 創(chuàng)建測(cè)試數(shù)據(jù)
        Product product = new Product(null, "筆記本電腦", 6999.99, 10);
        // 執(zhí)行POST請(qǐng)求
        mockMvc.perform(
                post("/products")  // POST請(qǐng)求
                    .contentType(MediaType.APPLICATION_JSON)  // 設(shè)置Content-Type
                    .header("Authorization", "Bearer token123")  // 添加自定義請(qǐng)求頭
                    .content(objectMapper.writeValueAsString(product))  // 請(qǐng)求體JSON
               )
               .andDo(MockMvcResultHandlers.print())  // 打印請(qǐng)求和響應(yīng)詳情
               .andExpect(status().isCreated())  // 期望返回201狀態(tài)碼
               .andExpect(header().exists("Location"))  // 驗(yàn)證響應(yīng)頭包含Location
               .andExpect(jsonPath("$.id", not(nullValue())))  // 驗(yàn)證ID已生成
               .andExpect(jsonPath("$.name", is("筆記本電腦")))  // 驗(yàn)證屬性值
               .andExpect(jsonPath("$.price", closeTo(6999.99, 0.01)));  // 驗(yàn)證浮點(diǎn)數(shù)
    }
    @Test
    void testSearchProducts() throws Exception {
        // 測(cè)試帶查詢參數(shù)的GET請(qǐng)求
        mockMvc.perform(
                get("/products/search")
                    .param("keyword", "電腦")  // 添加查詢參數(shù)
                    .param("minPrice", "5000")
                    .param("maxPrice", "10000")
               )
               .andExpect(status().isOk())
               .andExpect(jsonPath("$", hasSize(greaterThan(0))))  // 驗(yàn)證數(shù)組不為空
               .andExpect(jsonPath("$[0].name", containsString("電腦")));  // 驗(yàn)證結(jié)果包含關(guān)鍵詞
    }
}
// 簡(jiǎn)單的產(chǎn)品類
class Product {
    private Long id;
    private String name;
    private double price;
    private int stock;
    // 構(gòu)造函數(shù)、getter和setter略
    public Product(Long id, String name, double price, int stock) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.stock = stock;
    }
    // getter和setter略...
}

四、模擬服務(wù)層與依賴

4.1 使用@MockBean模擬服務(wù)

在測(cè)試控制器時(shí),通常需要模擬服務(wù)層的行為。Spring Boot提供了@MockBean注解,可以用來(lái)替換Spring容器中的bean為Mockito模擬對(duì)象。這種方式使得控制器測(cè)試可以專注于控制層邏輯,無(wú)需關(guān)心服務(wù)層的實(shí)際實(shí)現(xiàn)。通過(guò)配置模擬對(duì)象的返回值,可以測(cè)試控制器在不同場(chǎng)景下的行為。

package com.example.demo.controller;
import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Arrays;
import java.util.Optional;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(UserController.class)
public class UserControllerWithMockServiceTest {
    @Autowired
    private MockMvc mockMvc;
    @MockBean  // 創(chuàng)建并注入U(xiǎn)serService的模擬實(shí)現(xiàn)
    private UserService userService;
    @Test
    void testGetUserById() throws Exception {
        // 配置模擬服務(wù)的行為
        User mockUser = new User(1L, "張三", "zhangsan@example.com");
        when(userService.findById(1L)).thenReturn(Optional.of(mockUser));
        when(userService.findById(99L)).thenReturn(Optional.empty());  // 模擬用戶不存在的情況
        // 測(cè)試成功場(chǎng)景
        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.id").value(1))
               .andExpect(jsonPath("$.name").value("張三"));
        // 測(cè)試用戶不存在的場(chǎng)景
        mockMvc.perform(get("/users/99"))
               .andExpect(status().isNotFound());  // 期望返回404
    }
    @Test
    void testGetAllUsers() throws Exception {
        // 配置模擬服務(wù)返回用戶列表
        when(userService.findAll()).thenReturn(Arrays.asList(
            new User(1L, "張三", "zhangsan@example.com"),
            new User(2L, "李四", "lisi@example.com")
        ));
        // 測(cè)試獲取所有用戶API
        mockMvc.perform(get("/users"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$").isArray())
               .andExpect(jsonPath("$.length()").value(2))
               .andExpect(jsonPath("$[0].name").value("張三"))
               .andExpect(jsonPath("$[1].name").value("李四"));
    }
}
// User模型類
class User {
    private Long id;
    private String name;
    private String email;
    // 構(gòu)造函數(shù)、getter和setter略
    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
    // getter和setter略...
}

4.2 測(cè)試異常處理和邊界情況

全面的測(cè)試應(yīng)該包括對(duì)異常情況和邊界條件的處理。在SpringBoot應(yīng)用中,控制器通常會(huì)通過(guò)@ExceptionHandler或@ControllerAdvice處理異常。通過(guò)MockMvc可以有效地測(cè)試這些異常處理機(jī)制,確保系統(tǒng)在異常情況下也能夠正確響應(yīng)。測(cè)試邊界情況可以提高代碼的健壯性。

package com.example.demo.controller;
import com.example.demo.exception.ResourceNotFoundException;
import com.example.demo.service.OrderService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(OrderController.class)
public class OrderControllerExceptionTest {
    @Autowired
    private MockMvc mockMvc;
    @MockBean
    private OrderService orderService;
    @Test
    void testResourceNotFoundExceptionHandling() throws Exception {
        // 配置模擬服務(wù)拋出異常
        when(orderService.getOrderById(anyLong()))
            .thenThrow(new ResourceNotFoundException("Order not found with id: 999"));
        // 驗(yàn)證異常是否被正確處理
        mockMvc.perform(get("/orders/999"))
               .andExpect(status().isNotFound())  // 期望返回404
               .andExpect(jsonPath("$.message").value("Order not found with id: 999"))
               .andExpect(jsonPath("$.timestamp").exists());
    }
    @Test
    void testInvalidInputHandling() throws Exception {
        // 測(cè)試無(wú)效輸入的處理
        mockMvc.perform(
                post("/orders")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content("{\"customerName\":\"\",\"amount\":-10}")  // 無(wú)效數(shù)據(jù)
               )
               .andExpect(status().isBadRequest())  // 期望返回400
               .andExpect(jsonPath("$.fieldErrors").isArray())
               .andExpect(jsonPath("$.fieldErrors[?(@.field=='customerName')]").exists())
               .andExpect(jsonPath("$.fieldErrors[?(@.field=='amount')]").exists());
    }
    @Test
    void testUnauthorizedAccess() throws Exception {
        // 測(cè)試未授權(quán)訪問的處理
        doThrow(new SecurityException("Unauthorized access")).when(orderService)
            .deleteOrder(anyLong());
        mockMvc.perform(get("/orders/123/delete"))
               .andExpect(status().isUnauthorized())  // 期望返回401
               .andExpect(jsonPath("$.error").value("Unauthorized access"));
    }
}

五、測(cè)試最佳實(shí)踐

5.1 測(cè)試數(shù)據(jù)準(zhǔn)備與清理

良好的測(cè)試應(yīng)當(dāng)具有隔離性和可重復(fù)性。在SpringBoot測(cè)試中,應(yīng)當(dāng)注意測(cè)試數(shù)據(jù)的準(zhǔn)備和清理工作。使用@BeforeEach和@AfterEach注解可以在每個(gè)測(cè)試方法前后執(zhí)行準(zhǔn)備和清理操作。對(duì)于數(shù)據(jù)庫(kù)測(cè)試,可以使用@Sql注解執(zhí)行SQL腳本,或者配合@Transactional注解自動(dòng)回滾事務(wù)。

package com.example.demo.repository;
import com.example.demo.entity.Employee;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.jdbc.Sql;
import java.time.LocalDate;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest  // 專用于JPA倉(cāng)庫(kù)層測(cè)試的注解
public class EmployeeRepositoryTest {
    @Autowired
    private EmployeeRepository employeeRepository;
    @BeforeEach
    void setUp() {
        // 測(cè)試前準(zhǔn)備數(shù)據(jù)
        employeeRepository.saveAll(List.of(
            new Employee(null, "張三", "開發(fā)", 12000.0, LocalDate.of(2020, 5, 1)),
            new Employee(null, "李四", "測(cè)試", 10000.0, LocalDate.of(2021, 3, 15)),
            new Employee(null, "王五", "開發(fā)", 15000.0, LocalDate.of(2019, 8, 12))
        ));
    }
    @AfterEach
    void tearDown() {
        // 測(cè)試后清理數(shù)據(jù)
        employeeRepository.deleteAll();
    }
    @Test
    void testFindByDepartment() {
        // 測(cè)試按部門查詢
        List<Employee> developers = employeeRepository.findByDepartment("開發(fā)");
        assertThat(developers).hasSize(2);
        assertThat(developers).extracting(Employee::getName)
                             .containsExactlyInAnyOrder("張三", "王五");
    }
    @Test
    @Sql("/test-data/additional-employees.sql")  // 執(zhí)行SQL腳本添加更多測(cè)試數(shù)據(jù)
    void testFindBySalaryRange() {
        // 測(cè)試按薪資范圍查詢
        List<Employee> employees = employeeRepository.findBySalaryBetween(11000.0, 14000.0);
        assertThat(employees).hasSize(2);
        assertThat(employees).extracting(Employee::getName)
                             .contains("張三");
    }
}
// Employee實(shí)體類
class Employee {
    private Long id;
    private String name;
    private String department;
    private Double salary;
    private LocalDate hireDate;
    // 構(gòu)造函數(shù)、getter和setter略
    public Employee(Long id, String name, String department, Double salary, LocalDate hireDate) {
        this.id = id;
        this.name = name;
        this.department = department;
        this.salary = salary;
        this.hireDate = hireDate;
    }
    // getter略...
}

5.2 測(cè)試覆蓋率與持續(xù)集成

測(cè)試覆蓋率是衡量測(cè)試質(zhì)量的重要指標(biāo),高覆蓋率通常意味著更少的未測(cè)試代碼和更少的潛在bug。在SpringBoot項(xiàng)目中,可以使用JaCoCo等工具統(tǒng)計(jì)測(cè)試覆蓋率。將測(cè)試集成到CI/CD流程中,確保每次代碼提交都會(huì)觸發(fā)自動(dòng)測(cè)試,可以盡早發(fā)現(xiàn)問題,提高開發(fā)效率。

// 在build.gradle中配置JaCoCo測(cè)試覆蓋率插件
/*
plugins {
    id 'jacoco'
}
jacoco {
    toolVersion = "0.8.7"
}
test {
    finalizedBy jacocoTestReport  // 測(cè)試完成后生成覆蓋率報(bào)告
}
jacocoTestReport {
    dependsOn test  // 確保測(cè)試已執(zhí)行
    reports {
        xml.enabled true
        html.enabled true
    }
}
// 設(shè)置覆蓋率閾值
jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = 0.80  // 最低80%覆蓋率
            }
        }
    }
}
*/
// 示例測(cè)試類 - 確保高覆蓋率
package com.example.demo.service;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@SpringBootTest
public class TaxCalculatorServiceTest {
    @Autowired
    private TaxCalculatorService taxCalculatorService;
    @ParameterizedTest
    @CsvSource({
        "5000.0, 0.0",       // 不超過(guò)起征點(diǎn)
        "8000.0, 90.0",      // 第一檔稅率3%
        "20000.0, 1590.0",   // 第二檔稅率10%
        "50000.0, 7590.0"    // 第三檔稅率20%
    })
    void testCalculateIncomeTax(double income, double expectedTax) {
        double tax = taxCalculatorService.calculateIncomeTax(income);
        assertThat(tax).isEqualTo(expectedTax);
    }
    @Test
    void testCalculateIncomeTaxWithNegativeIncome() {
        // 測(cè)試邊界情況:負(fù)收入
        assertThatThrownBy(() -> taxCalculatorService.calculateIncomeTax(-1000.0))
            .isInstanceOf(IllegalArgumentException.class)
            .hasMessageContaining("Income cannot be negative");
    }
    // 更多測(cè)試用例,確保高覆蓋率...
}

總結(jié)

本文詳細(xì)介紹了SpringBoot測(cè)試環(huán)境中@SpringBootTest注解與MockMvc測(cè)試框架的實(shí)戰(zhàn)應(yīng)用。@SpringBootTest提供了加載完整應(yīng)用上下文的能力,支持不同的Web環(huán)境模式,適用于各種集成測(cè)試場(chǎng)景。MockMvc則專注于控制器層測(cè)試,通過(guò)模擬HTTP請(qǐng)求和響應(yīng),無(wú)需啟動(dòng)真實(shí)服務(wù)器即可驗(yàn)證控制器行為。在實(shí)際開發(fā)中,合理配置測(cè)試環(huán)境、準(zhǔn)備測(cè)試數(shù)據(jù)、模擬服務(wù)依賴、處理異常和邊界情況,對(duì)于構(gòu)建健壯的測(cè)試體系至關(guān)重要。遵循最佳實(shí)踐,如保持測(cè)試隔離性、追求高測(cè)試覆蓋率、集成自動(dòng)化測(cè)試流程等,能夠顯著提高代碼質(zhì)量和開發(fā)效率。通過(guò)本文介紹的技術(shù)和方法,開發(fā)者可以構(gòu)建更加可靠和高效的SpringBoot應(yīng)用測(cè)試體系,為項(xiàng)目的長(zhǎng)期穩(wěn)定運(yùn)行提供有力保障。

到此這篇關(guān)于SpringBoot測(cè)試之@SpringBootTest與MockMvc的實(shí)戰(zhàn)應(yīng)用小結(jié)的文章就介紹到這了,更多相關(guān)SpringBoot測(cè)試@SpringBootTest與MockMvc內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論