# 集成测试中 createTestApp 默认 override 拦截器导致横切模块测试失效

**日期**: 2026-05-08
**上下文**: 写审计模块（audit-system）L1 集成测试时发现并绕开

## 问题

`testing/backend/helpers/app.helper.ts` 的 `createTestApp()` 在第 30-35 行
**主动 override 掉 `APP_INTERCEPTOR`** 为空拦截器：

```ts
.overrideProvider(APP_INTERCEPTOR)
.useValue({
  intercept: (context, next) => next.handle(),
})
```

理由是"避免审计日志在测试中触发外键约束错误"。但这意味着**任何依赖
APP_INTERCEPTOR 的横切模块**（审计、scope guard、tracing 等）在用
`createTestApp()` 的测试里**都不会被验证**。

测试侧症状：你 `expect(audit_log.count >= before+1)` 永远失败，因为审计
拦截器根本没运行。但请求本身 200 成功，让人误以为是 timing 问题。

## 解决方案

在模块本地 `_helpers.ts` 写一份**不 override** 的 `createTestApp` 变体：

```ts
import { Test } from '@nestjs/testing';
import { AppModule } from '@/app.module';
// ... ValidationPipe / TransformInterceptor / AllExceptionsFilter

export async function createAuditTestApp() {
  const moduleFixture = await Test.createTestingModule({
    imports: [AppModule],
  }).compile();  // 不 override APP_INTERCEPTOR

  const app = moduleFixture.createNestApplication();
  // 复制 createTestApp 的剩余配置（apiPrefix / pipes / filters）
  // ...
  await app.init();
  return app;
}
```

**不要直接修改公共 `app.helper.ts`** —— 其他模块测试可能依赖空拦截器
避免 audit FK 错误。横切模块测试需要在自己的 _helpers.ts 自建。

## 配套坑（写测试时一并注意）

1. **`@Auditable()` 才触发审计**：拦截器只对带 `@Auditable()` 装饰器的
   handler 生效。`/users/me`、`/users/:id` 等读接口通常没标记 → 测试要触发
   写日志，得用 `/auth/login`（已知 @Auditable）或带装饰器的业务端点。

2. **拦截器异步落库**：HTTP 200 返回时 audit_log 可能还没写。断言前
   `await new Promise(r => setTimeout(r, 300-400))`。

3. **hash 自检要包含所有字段 + 显式 id**：
   `prisma.auditLog.create({ data })` 中 record 必须显式包含**所有
   nullable 字段**（`why: null`、`changes: null`、`signature: null` 等）
   且**显式 `id: randomUUID()`**，否则 Prisma 自动填充后从 DB round-trip
   回来的对象与计算 hash 时的对象字段集合不同 → hash 对不上。

4. **NestJS POST 默认 201**：测试 `POST /audit/integrity-check` 要
   `.expect(201)` 不是 200（除非 controller 显式 `@HttpCode(200)`）。

5. **权限只走角色**：项目权限模型只支持 `role → permission`，没有直接
   `user → permission`。测试给非 admin 加权限要走"建测试角色 → 加 perm
   关联 → 分配给 user"三步。表名注意：`Role` / `Permission` /
   `RolePermission` / `UserRole`（不是 RolePermissionRel 等）。

6. **Administrator 默认 bypass `@RequirePermissions`**：
   `permissions.guard.ts:71 isAdministrator(user)` 直接放行，所以
   setupIntegrationTest 创建的 admin token happy path 全过，**403 测试
   必须独立创建非 admin 用户走完整 login 流程**。

## 适用面

凡是 NestJS 项目里**通过 APP_INTERCEPTOR 实现的横切关注点**——审计、
日志聚合、scope guard、链路追踪、metrics 收集——的 L1 集成测试都受影响。
碰到"代码看起来对，测试就是不通过"的横切模块场景，**第一件事是确认
createTestApp 没有 override 掉你要测的拦截器**。

## 相关 commit

- `5dd18de7` fix(audit): integrity-check scope 枚举对齐 + 补全 report 权限 seed (B1+B2)
- `47638538` fix(audit): list/detail formatter 补齐前端契约缺失字段 (C1+C2)
- `6b4391eb` test(audit): 新增 L1 jest 集成测试套件 21/21 通过
