主题
集成测试与问题排查
一、集成测试:全链路验证
集成测试让"Controller → Service → Mapper → MySQL"真实跑通,用 MockMvc 模拟 HTTP 请求:
java
package com.mall.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mall.dto.CartAddDTO;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest
@AutoConfigureMockMvc
class CartControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Test
void 商品列表可查询() throws Exception {
mockMvc.perform(get("/api/product/list")
.param("page", "1").param("size", "10"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data.records").exists());
}
@Test
void 注册后可登录() throws Exception {
mockMvc.perform(post("/api/auth/register")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"username\":\"test01\",\"password\":\"123456\"}"))
.andExpect(jsonPath("$.code").value(0));
// SQL 层面唯一约束:重复注册应返回业务错误
mockMvc.perform(post("/api/auth/register")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"username\":\"test01\",\"password\":\"123456\"}"))
.andExpect(jsonPath("$.code").value(500));
}
}注意事项:
- 集成测试连真实数据库,跑之前保证
mall库存在。 - 可以把测试库与开发库隔离(
application-test.yml配独立库),避免污染数据。 - 每个用例自己造数据并清理,顺序相互独立。
二、前端单元测试(可选加分)
Vue / React 项目都可用 Vitest + Testing Library(create-vue 脚手架默认带了 Vitest):
ts
// web-vue/src/views/HomeView.test.ts
import { describe, it, expect } from 'vitest'
describe('价格格式化', () => {
it('数字转货币格式', () => {
expect(formatPrice(2999)).toBe('¥2,999.00')
})
})前端测试重点放在纯函数/工具函数(格式化、计算),组件测试成本高,项目紧可后补。
三、问题排查工具箱
1. 看后端 SQL(MP 已默认打印)
==> Preparing: SELECT id,name,price FROM product WHERE deleted=0 AND name LIKE ? ...
==> Parameters: %手机%(String)这条 SQL 对不上预期 → 到这就能发现问题。
2. 浏览器 Network 面板
- 看请求 URL 是否经过代理(
Request URL前应显示localhost:5173,但请求到后端走通了)。 - 看 响应:JSON 里
code/message/data是否符合预期。
3. 后端日志分级排查
bash
# 控制台实时看
# 或查看日志文件(生产环境)
tail -f logs/application.log
grep -n "ERROR" logs/application.log4. 常见疑难场景速查
| 场景 | 排查方向 |
|---|---|
| 页面 502/504 | 后端没启动 / 被代理但端口错了 |
| 数据偶发不一致 | 事务边界放错、并发问题(看第 7 部分) |
| 前端拿到的是旧数据 | 浏览器缓存 / localStorage 里的旧 token |
| 时区差 8 小时 | JDBC URL 加 serverTimezone=Asia/Shanghai |
| 中文乱码 | 建库用 utf8mb4、连接串加 characterEncoding=utf8 |
四、全链路冒烟测试(上线前必做)
用第 8 部分联调那套流程,写成一个脚本化冒烟清单,上线前快速过一遍:
bash
1. GET /api/product/list → code=0,有数据
2. POST /api/auth/register → code=0
3. POST /api/auth/login → 拿到 token
4. POST /api/cart(带token) → code=0
5. POST /api/order(带token) → code=0,库存减少
6. GET /api/order/list → 能看到刚下的单可以手跑,也可以写进 CI(第 9 部分)每天自动跑一遍。
五、本章验收
- [ ]
CartControllerTest/ProductControllerTest等集成测试通过 - [ ] 会用 Network 面板 + MP 打印的 SQL 定位一个问题
- [ ] 完成一次全链路冒烟
- [ ] 顺手把常见的"时区/乱码"坑配置正确
核心心法
排错 = 缩小范围:前端 → 网络 → 后端 → SQL → 数据库,一层层往下找。用日志和数据定位,别凭感觉改代码。