| 註解 | 作用 |
@RunWith(SpringRunner.class) | JUnit 4 整合 Spring TestContext 框架(Spring Boot 2.2+ 推薦 SpringRunner 別名) |
@SpringBootTest | 啟動完整 Spring Boot 上下文,支援 webEnvironment 區分 MOCK/真實端口 |
@WebAppConfiguration | 聲明 Web 環境,注入 ServletContext(非 Web 可省略) |
@Autowired | 測試類中直接注入 Bean |
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 等現代特性)。
- 上一篇文章: Java 構造方法全解析:重載、鏈式調用、默認構造、繼承鏈與訪問權限控制
- 下一篇文章: JAXB 實戰指南:XML 與 Java 對象雙向轉換、核心註解詳解與最佳實踐
Copyright ©
程式碼之家 All Rights Reserved