测试入门
Laravel 用 PHPUnit +
php artisan test;Spring Boot 用 JUnit 5 +mvn test,测试代码放src/test/java/,与主代码包结构一一对应。这篇先建立「Java 测试怎么组织」的整体认知。
测试结构
src/
├── main/java/com/example/blog/...
└── test/java/com/example/blog/
├── post/PostServiceTest.java ← 单元测试
└── post/PostControllerTest.java ← 集成测试测试类命名规范:被测类名 + Test。运行方式:
bash
./mvnw test # 跑全部测试
./mvnw test -Dtest=PostServiceTest # 只跑某个测试类TIP
对应 Laravel:
| Laravel | Spring Boot |
|---|---|
phpunit.xml | pom.xml 的 test 依赖 |
tests/Feature、tests/Unit | src/test/java 按包分 |
php artisan test | ./mvnw test |
@test 方法 | @Test 注解方法 |
第一个单元测试
java
package com.example.blog.post;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PostServiceTest {
@Test
void 计算标题字数() { // 方法名可以用中文(可读性更好)
String title = "Spring Boot 入门";
assertEquals(16, title.length());
}
@Test
void 空标题应该失败() {
String title = "";
assertTrue(title.isBlank());
}
}TIP
JUnit 5 用 @Test 标注测试方法,断言方法在 org.junit.jupiter.api.Assertions:
assertEquals(expected, actual)assertTrue / assertFalseassertNotNull / assertNullassertThrows(RuntimeException.class, () -> ...)(断言抛异常,对应 Laravel 的expectException)
单元测试 vs 集成测试
| 类型 | 测什么 | 用不用数据库 | Spring 上下文 |
|---|---|---|---|
| 单元测试 | 单个类/方法逻辑 | 不用(Mock 掉依赖) | 不启动(快) |
| 集成测试 | 多层协作、完整请求 | 用(H2/Testcontainers) | 启动完整上下文(慢) |
java
// 单元测试:只测 Service 逻辑,把 Repository mock 掉
// 集成测试:@SpringBootTest + MockMvc,真实打接口TIP
./mvnw test 默认两种都跑。单元测试要快(毫秒级),集成测试要少而精(跑一次秒级)。Laravel 的 Unit / Feature 区别同理。
测试专用配置
测试用独立配置,别污染开发库。src/test/resources/application-test.yml:
yaml
spring:
datasource:
url: jdbc:h2:mem:testdb;MODE=MySQL
jpa:
hibernate:
ddl-auto: create-drop # 测试库自动建表
sql:
init:
mode: never测试类上指定 Profile:
java
@SpringBootTest
@ActiveProfiles("test")
class PostServiceIntegrationTest { ... }TIP
测试数据库原则:用内存库(H2)或 Testcontainers 起真实库,绝不用开发/生产库。对应 Laravel 的 phpunit.xml 里配 DB_DATABASE=:memory:。
测试生命周期注解
| 注解 | 作用 |
|---|---|
@BeforeEach | 每个测试前执行(≈ setUp()) |
@AfterEach | 每个测试后执行 |
@BeforeAll | 测试类所有用例前执行一次 |
@AfterAll | 全部结束后执行一次 |
java
class PostServiceTest {
@BeforeEach
void setUp() {
// 每个测试前重置状态
}
}测试金字塔(和 Laravel 一样的道理)
╱ 少数集成测试(跑通链路)
╱ 多些 Service 测试(核心业务逻辑)
╱ 大量单元测试(快、稳、覆盖边界)- 业务逻辑放 Service 层 + 重点测 Service(Java 尤其如此:Controller 薄,逻辑都在 Service)
- Controller 用 MockMvc 做轻量集成测试
- 别为了覆盖率测 getter/setter
为什么 Service 测试是重点?
Java 的 @Transactional、@Cacheable 等关键逻辑都在 Service 层,且 Service 是依赖注入的中心。Service 测试 ≈ Laravel 的「控制器逻辑 + Model 逻辑」测试,覆盖它性价比最高。
实战建议
- 测试方法名用中文描述行为(
void 未登录访问返回401()),比testLogin1可读 - 一个测试只断言一件事
- 集成测试用 H2/Testcontainers,测试完数据自动清理
- 关键业务(支付、订单、权限)必须测,简单 CRUD 可以少测
下一节:HTTP 测试(MockMvc 打接口)和 模拟对象(Mockito)(mock 依赖)。