首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Boot 單元測試實戰:JUnit 4/5、MockMvc、參數化測試、REST API 測試與輸出捕獲全攻略

     編輯:Java 綜合教學

為什麼要寫單元測試?

  • 防回歸:重構/修改代碼時,測試套件即時捕獲破壞性變更。
  • 文檔化:測試代碼是最佳的「可執行文檔」,展示 API 預期行為。
  • CI/CD 門禁:打包前自動跑測,保證交付質量。

Spring Boot 2.x + JUnit 4 基礎配置

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class) // 啟動完整 Spring 上下文
@WebAppConfiguration // 模擬 ServletContext(Web 環境必需)
public class ServiceLayerTest {

    @Autowired
    private UserService userService;

    @Test
    public void testFindByName() {
        List<User> users = userService.findByName("張三");
        assertFalse(users.isEmpty());
        assertEquals("張三", users.get(0).getName());
    }
}

核心註解速查

JUnit 4 常用生命週期註解

@BeforeClass  // 所有測試前運行一次(static 方法),適合初始化昂貴資源(如數據庫連接池)
@AfterClass   // 所有測試後運行一次,釋放資源
@Before       // 每個 @Test 前運行,重置狀態、構造測試數據
@After        // 每個 @Test 後運行,清理副作用

@Test(timeout = 1000)           // 超時 1 秒判定失敗
@Test(expected = Exception.class) // 預期拋出指定異常
@Ignore("原因")                  // 暫時忽略該測試/類

參數化測試:一個方法跑多組數據

@RunWith(Parameterized.class)
public class StringUtilsTest {
    private String input;
    private boolean expected;

    public StringUtilsTest(String input, boolean expected) {
        this.input = input; this.expected = expected;
    }

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{
            {"hello", true}, {"", false}, {null, false}
        });
    }

    @Test
    public void testIsNotBlank() {
        assertEquals(expected, StringUtils.isNotBlank(input));
    }
}

注意:@RunWith 只能指定一個,若需 Spring 整合又想參數化,可用 assertArrayEquals 或 JUnit 5 @ParameterizedTest 替代。

測試套件:批量執行多個測試類

@RunWith(Suite.class)
@SuiteClasses({UserServiceTest.class, OrderServiceTest.class, PayServiceTest.class})
public class AllServiceSuite { /* 空類即可 */ }

REST API 整合測試:TestRestTemplate / MockMvc

方案一:TestRestTemplate(真實端口,全鏈路)

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

    @Autowired private TestRestTemplate restTemplate;
    @LocalServerPort private int port;

    @Test
    public void testHello() {
        String url = "https://localhost:" + port + "/api/hello?name=Tom";
        ResponseEntity<String> resp = restTemplate.getForEntity(url, String.class);
        assertEquals(HttpStatus.OK, resp.getStatusCode());
        assertTrue(resp.getBody().contains("Tom"));
    }
}

方案二:MockMvc(無端口,單元級,速度快)

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class) // 只載入 Web 層
public class ControllerMockTest {

    @Autowired private MockMvc mockMvc;
    @MockBean private HelloService helloService; // Mock 服務層

    @Test
    public void testHello() throws Exception {
        when(helloService.sayHello("Tom")).thenReturn("Hello Tom");
        mockMvc.perform(get("/api/hello").param("name", "Tom"))
               .andExpect(status().isOk())
               .andExpect(content().string(containsString("Tom")));
    }
}

輸出捕獲:驗證日誌/控制台輸出

@Rule
public OutputCapture capture = new OutputCapture();

@Test
public void testLogOutput() {
    log.info("用戶登入: userId=100");
    assertThat(capture.toString(), containsString("userId=100"));
}

斷言最佳實踐:assertArrayEquals 替代 assertEquals

// 推薦:一次驗證多組輸入輸出
assertArrayEquals(
    new Object[]{ true, false, true },
    new Object[]{
        service.likeName("小明").size() > 0,
        service.likeName("壞").size() > 0,
        service.likeName("莉莉").size() > 0
    }
);

避坑清單

  • @SpringBootTest vs @WebMvcTest:前者啟動全上下文(慢、整合測試),後者只載 Web 層(快、控制器單測)。
  • 事務回滾:測試方法默認加 @Transactional 並自動回滾,需持久化時加 @Commit 或 @Rollback(false)。
  • 測試數據隔離:用 @Sql 腳本初始化/清理,或 TestExecutionListener 管理。
  • JUnit 5 遷移:新專案優先用 Jupiter(@ParameterizedTest, @DisplayName, @Nested 等現代特性)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
註解作用
@RunWith(SpringRunner.class)JUnit 4 整合 Spring TestContext 框架(Spring Boot 2.2+ 推薦 SpringRunner 別名)
@SpringBootTest啟動完整 Spring Boot 上下文,支援 webEnvironment 區分 MOCK/真實端口
@WebAppConfiguration聲明 Web 環境,注入 ServletContext(非 Web 可省略)
@Autowired測試類中直接注入 Bean