You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何消除Jest e2e测试中重复创建账号与API Key的冗余代码

Jest + Supertest E2E测试冗余问题解决方案

方案1:单次创建API Key供全用例复用

Jest 同个describe块作用域内声明的变量,会在整个测试套件运行期间保存在内存中,配合beforeAll钩子(所有同块测试用例执行前仅运行1次),不需要额外持久化就能实现跨用例状态共享,这是E2E测试里最常用的全局初始化方案。
核心改动是在测试块顶层声明存储账号ID、API Key的共享变量,在beforeAll初始化应用后一次性完成账号和Key的创建,后续所有测试用例直接读取变量值即可,不用重复发创建请求。
核心实现代码:

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import { randBrand } from '@ngneat/falso';

describe('All e2e tests', () => {
  let app: INestApplication;
  // 声明跨用例共享变量
  let sharedAccountId: string;
  let sharedApiKey: string;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();

    // 仅执行1次:创建测试账号和API Key
    const testAccountName = randBrand();
    const accountRes = await request(app.getHttpServer())
      .post('/accounts')
      .send({ name: testAccountName })
      .expect(201);
    sharedAccountId = accountRes.body._id;

    const keyRes = await request(app.getHttpServer())
      .post('/apikeys')
      .send({ accountId: sharedAccountId })
      .expect(201); // 注意统一状态码,和接口实际返回保持一致
    sharedApiKey = keyRes.body.apiKey;
  });

  afterAll(async () => {
    await app.close();
  });

  describe('Users (e2e)', () => {
    it('patches an user (PATCH)', async () => {
      // 直接使用全局共享的API Key,无需重复创建
      const res = await request(app.getHttpServer())
        .patch('/users/1')
        .send({ name: 'SomeUser', properties: { age: '20' } })
        .set('Accept', 'application/json')
        .set('x-api-Key', sharedApiKey)
        .expect(201);

      expect(res.body.accountId).toEqual(sharedAccountId);
      expect(res.body.name).toEqual('SomeUser');
    });
  });

  describe('Events (e2e)', () => {
    it('creates an event (POST)', async () => {
      // 直接复用共享Key
      const res = await request(app.getHttpServer())
        .post('/events')
        .send({
          name: 'login',
          userId: '1',
          groupId: '2',
          properties: { client: 'mobile' },
        })
        .set('Accept', 'application/json')
        .set('x-api-Key', sharedApiKey)
        .expect(201);

      expect(res.body.accountId).toEqual(sharedAccountId);
      expect(res.body.name).toEqual('login');
    });
  });
});

注意:如果测试用例存在修改/删除API Key、改动账号状态的操作,会导致其他用例鉴权失败,这类场景下不要用全局共享Key,改用方案2。

方案2:抽离公共创建逻辑为可复用工具函数

如果测试场景需要每个用例使用独立的账号/Key(比如测试权限隔离、资源归属逻辑),可以把重复的创建逻辑抽成独立的异步工具函数,需要的时候直接调用即可,不用重复写嵌套请求逻辑。

第一步:定义工具函数

可以直接写在测试文件顶部,或者抽到单独的测试工具文件中:

/**
 * 创建测试账号及对应API Key
 * @param app Nest应用实例
 * @returns 包含accountId和apiKey的对象
 */
async function createTestAccountAndKey(app: INestApplication) {
  const accountName = randBrand();
  const accountRes = await request(app.getHttpServer())
    .post('/accounts')
    .send({ name: accountName })
    .expect(201);
  const accountId = accountRes.body._id;

  const keyRes = await request(app.getHttpServer())
    .post('/apikeys')
    .send({ accountId })
    .expect(201);

  return {
    accountId,
    apiKey: keyRes.body.apiKey
  };
}

第二步:在用例中直接调用

所有需要凭证的用例,一行代码就能拿到独立的测试账号和Key:

describe('Events (e2e)', () => {
  it('creates an event (POST)', async () => {
    // 直接调用工具函数获取独立测试凭证
    const { accountId, apiKey } = await createTestAccountAndKey(app);

    const res = await request(app.getHttpServer())
      .post('/events')
      .send({
        name: 'login',
        userId: '1',
        groupId: '2',
        properties: { client: 'mobile' },
      })
      .set('Accept', 'application/json')
      .set('x-api-Key', apiKey)
      .expect(201);

      expect(res.body.accountId).toEqual(accountId);
      expect(res.body.name).toEqual('login');
  });
});

额外优化建议

  • 优先使用async/await语法代替多层.then()嵌套,代码可读性更高,也不容易出现回调层级错误
  • 原代码中重复设置了两次Accept请求头,保留一处即可
  • 注意对齐接口实际返回的状态码,现有代码中创建API Key的断言混用了200和201,统一后可以避免不必要的测试报错
  • 两种方案可以结合使用:普通无副作用的接口测试用全局共享Key提升测试速度,需要隔离性的测试场景用工具函数创建独立凭证

内容的提问来源于stack exchange,提问作者Luis Novo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 09:27:35