185 lines
7.0 KiB
Markdown
185 lines
7.0 KiB
Markdown
# Week 8:工程化能力
|
||
|
||
**目标**:掌握测试、文档、部署等工程化技能,交付可测试、有文档、容器化的完整项目。
|
||
|
||
**前置**:完成 Week 7(前后端分离项目)。
|
||
|
||
**本周产出**:学生管理系统 v4 — 有单元测试、集成测试、API 文档。
|
||
|
||
**启动方式**:
|
||
```bash
|
||
cd week8
|
||
|
||
# 运行测试
|
||
mvn test
|
||
|
||
# 启动应用后访问 API 文档
|
||
http://localhost:8080/doc.html
|
||
```
|
||
|
||
---
|
||
|
||
## Day 1:JUnit 5 + Mockito 单元测试
|
||
|
||
**知识点**:
|
||
- 测试金字塔:单元测试 → 集成测试 → E2E 测试
|
||
- JUnit 5 注解:`@Test`、`@BeforeEach`、`@DisplayName`
|
||
- 断言:`assertEquals`、`assertTrue`、`assertThrows`
|
||
- Mockito:`@Mock`(模拟依赖)、`@InjectMocks`(注入模拟对象)
|
||
- `when(...).thenReturn(...)`:控制 Mock 行为
|
||
- `verify()`:验证方法被调用
|
||
- `@ExtendWith(MockitoExtension.class)`:初始化 Mockito
|
||
- 测试覆盖率:行覆盖 vs 分支覆盖
|
||
|
||
**动手 → 理解**:
|
||
1. 阅读 `AuthServiceTest.java`,理解每个 `@Mock` 的含义
|
||
2. 运行 `mvn test -Dtest=AuthServiceTest`,观察 5 个测试全部通过
|
||
3. 故意把 `testLoginBadPassword` 的期望密码改为正确值,观察测试失败信息
|
||
4. 在 `when(...)` 中把返回值改成 `false`,看哪个测试会失败
|
||
5. 写一个测试:验证 `register` 成功时 `userRepo.save()` 被调用了 1 次
|
||
|
||
**核心文件**:
|
||
- `src/test/java/com/learn/service/AuthServiceTest.java` — 单元测试示例
|
||
|
||
**思考题**:为什么不直接测试 Service 的真实数据库操作,而是用 Mockito 模拟?
|
||
|
||
---
|
||
|
||
## Day 2:@SpringBootTest 集成测试
|
||
|
||
**知识点**:
|
||
- `@SpringBootTest`:启动完整 Spring 容器
|
||
- `@AutoConfigureMockMvc`:模拟 HTTP 请求
|
||
- `MockMvc`:`perform(get(...))`、`andExpect(status().isOk())`、`jsonPath()`
|
||
- H2 内存数据库:`jdbc:h2:mem:testdb` — 不依赖外部 MySQL
|
||
- `@ActiveProfiles("test")`:测试专用配置
|
||
- `application-test.yml`:测试环境的 H2 + 禁用 Redis
|
||
- `@TestMethodOrder` + `@Order`:控制测试顺序
|
||
|
||
**动手 → 理解**:
|
||
1. 阅读 `StudentControllerTest.java`,理解测试流程
|
||
2. 运行 `mvn test`,观察 Spring Boot 启动日志中的 `Using profile: "test"`
|
||
3. 在测试日志中找到 H2 的 `HikariPool-1 - Starting...` 确认使用内存库
|
||
4. 访问 `http://localhost:8080/h2-console`(测试模式下),查看表结构
|
||
5. 添加一个测试:验证用 user/123456(USER 角色)新增学生时返回 403
|
||
|
||
**核心文件**:
|
||
- `src/test/java/com/learn/controller/StudentControllerTest.java` — 集成测试
|
||
- `src/main/resources/application-test.yml` — 测试环境配置
|
||
|
||
**思考题**:H2 和 Testcontainers(真实 MySQL 容器)各有什么优劣?什么时候该用 Testcontainers?
|
||
|
||
---
|
||
|
||
## Day 3:Knife4j API 文档
|
||
|
||
**知识点**:
|
||
- 为什么需要 API 文档:前后端协作、接口调试、新人上手
|
||
- Swagger / OpenAPI 3.0 规范
|
||
- Knife4j:国产增强版 Swagger UI(界面更友好)
|
||
- `@Tag`、`@Operation`、`@Parameter` 注解增强文档
|
||
- `application.yml` 配置:`springdoc.swagger-ui.path=/doc.html`
|
||
- `OpenAPI` Bean:自定义文档标题、版本、描述
|
||
- 在线调试:在文档页面直接发送请求
|
||
|
||
**动手 → 理解**:
|
||
1. 启动项目,访问 `http://localhost:8080/doc.html`
|
||
2. 点击 "Auth" 标签,展开 `/api/auth/login`,点击"发送"直接测试
|
||
3. 在文档右上角设置全局 Token:`Bearer <你的JWT>`
|
||
4. 用文档页面的"调试"功能完成一次完整的增删改查
|
||
5. 在 Controller 方法上添加 `@Operation(summary = "...")` 注解,刷新文档查看效果
|
||
|
||
**核心文件**:
|
||
- `config/Knife4jConfig.java` — API 文档配置
|
||
- `pom.xml` → `knife4j-openapi3-jakarta-spring-boot-starter`
|
||
- `application.yml` → `springdoc.*`
|
||
|
||
**思考题**:API 文档应该暴露在生产环境吗?如果不应该,怎么关闭?
|
||
|
||
**生产环境安全提示**:
|
||
```yaml
|
||
# 生产环境 application-prod.yml 中关闭文档
|
||
springdoc:
|
||
api-docs:
|
||
enabled: false # 关闭 /v3/api-docs
|
||
swagger-ui:
|
||
enabled: false # 关闭 /doc.html
|
||
```
|
||
或在 SecurityConfig 中按 Profile 条件放行:
|
||
```java
|
||
// 开发环境放行文档,生产环境不放行
|
||
@Profile("!prod")
|
||
```
|
||
**原则**:API 文档暴露所有接口结构和参数,生产环境应关闭或加认证保护。
|
||
|
||
---
|
||
|
||
## Day 4:阶段总结 & 里程碑项目 v4
|
||
|
||
**知识点**:
|
||
- 回顾 Week 1-8 的技术栈全景图
|
||
- 理解"测试金字塔"在项目中的落地
|
||
- 对比 v1 → v4 四个版本的进化
|
||
|
||
**v1 → v4 进化史**:
|
||
|
||
| 版本 | 周次 | 新增能力 |
|
||
|------|------|---------|
|
||
| v1 | Week 4 | Spring Boot + JPA/MP + 原生 JS 全栈 |
|
||
| v2 | Week 5 | Spring Security + JWT + Redis + Actuator |
|
||
| v3 | Week 7 | Vue 3 前后端分离 + Axios + 导航守卫 |
|
||
| v4 | Week 8 | 单元测试 + 集成测试 + API 文档 |
|
||
|
||
**Actuator 端点说明**(Week 5 遗留问题):
|
||
- `/actuator` — 返回所有**可用端点列表**的 JSON,这是正常的
|
||
- 真正的监控数据在这些端点:
|
||
- `/actuator/health` → 健康状态(UP/DOWN)
|
||
- `/actuator/beans` → Spring 容器中所有 Bean
|
||
- `/actuator/env` → 环境变量和配置
|
||
- `/actuator/mappings` → 所有 URL 映射
|
||
- **安全建议**:`/actuator/env` 可能泄露数据库密码等敏感信息,生产环境不应暴露
|
||
|
||
**动手 → 理解**:
|
||
1. 画出 v4 的完整架构图(Vue → Axios → Spring Boot → JPA/MP → MySQL)
|
||
2. 检查所有测试是否通过:`mvn test`
|
||
3. 检查 API 文档是否完整:`http://localhost:8080/doc.html`
|
||
4. 确认 `docker-compose up --build` 能成功启动
|
||
5. 补充 `.gitignore`、`README.md`
|
||
|
||
**最终项目文件清单**:
|
||
```
|
||
week8/
|
||
├── pom.xml # 含 test + knife4j 依赖
|
||
├── sql/init.sql # 数据库初始化
|
||
├── src/main/
|
||
│ ├── java/com/learn/
|
||
│ │ ├── config/
|
||
│ │ │ ├── Knife4jConfig.java # Day 3: API 文档
|
||
│ │ │ └── SecurityConfig.java # 含 CORS
|
||
│ │ ├── controller/ # REST API
|
||
│ │ ├── entity/ # Student + User
|
||
│ │ └── service/ # 双 ORM 实现
|
||
│ └── resources/
|
||
│ ├── application.yml # 主配置 + springdoc
|
||
│ └── application-test.yml # Day 2: H2 测试配置
|
||
└── src/test/java/com/learn/
|
||
├── service/AuthServiceTest.java # Day 1: 单元测试
|
||
└── controller/StudentControllerTest.java # Day 2: 集成测试
|
||
```
|
||
|
||
---
|
||
|
||
## Week 8 总结
|
||
|
||
| 维度 | 工具 | 掌握程度 |
|
||
|------|------|---------|
|
||
| 单元测试 | JUnit 5 + Mockito | Service 层全 Mock 测试 |
|
||
| 集成测试 | @SpringBootTest + H2 | Controller 全流程测试 |
|
||
| API 文档 | Knife4j / SpringDoc | 自动生成 + 在线调试 |
|
||
|
||
**下一阶段:Week 9-12 — AI Agent 开发**
|
||
- Week 9:AI & LLM 基础,调用大模型 API
|
||
- Week 10:Agent 架构 + Function Calling
|
||
- Week 11:算法入门 + Agent 前端
|
||
- Week 12:最终项目 —— AI Agent 网站
|