## [ERR-20260418-002] 集成测试断言应匹配 error.code，不是错误消息关键字

**日期**: 2026-04-18
**类别**: 测试编写惯例
**严重度**: 低（一次性修复，但容易重复）

### 问题描述

重构业务错误消息从中文改成英文 + `RobotError` code 后，集成测试的这类断言会失败：

```ts
expect(res.body.error?.message || res.body.message).toMatch(/客户/);
```

因为错误消息变成 "Must bind a customer before reserving (customerId required)"，不再含"客户"二字。

### 根本原因

集成测试断言**错误消息关键字**（而不是错误 code），让测试耦合到 UI 文案语言。凡是以下场景都会让测试失败：
1. 消息改语言（中→英、英→中）
2. 消息改措辞（如"客户未绑定" → "必须先绑定客户"）
3. 消息加前缀/后缀（如加 `[MODULE]` 或 error code 前缀）

### 绕行方案（推荐规则）

**集成测试优先断言 `error.code`，不断言消息文本**：

```ts
// ❌ 差：耦合到消息文案
expect(res.body.error?.message).toMatch(/客户/);

// ✅ 好：断言稳定的错误码
expect(res.body.error?.code).toBe('ROBOT_MUST_BIND_CUSTOMER_BEFORE_RESERVE');
```

### 项目约定

- 所有业务 `throw` 用 `{ code: ModuleError.XXX, message: 'English fallback' }` 对象（参考 `backend/src/modules/robot-manager/errors/robot-manager.errors.ts`）
- 全局 HttpExceptionFilter 把 code 放到响应 `error.code`
- 前端按 code 做 i18n 翻译；查不到则 fallback 到 message
- 集成测试断言用 code；端到端 / UI 测试可以断言翻译后的消息

### 预防措施

- 写测试时第一眼看 service 源码，确认抛的是 code-bearing exception；如是，断言 code
- 代码 review 时看到 `.toMatch(/中文字符/)` 或 `.toMatch(/english phrase/)` 针对错误消息的，都应该建议改成 `.toBe(XXX_CODE)`

### Metadata
- Reproducible: yes（改消息后测试必现）
- Related Files: backend/src/modules/*/errors/*.ts, testing/backend/integration/**

---
