如何在Nest.js E2E测试中Mock嵌套模块的S3客户端?
Nest.js E2E测试中Mock aws-sdk-v3-nest的S3Client
你当前的mock代码不生效,核心原因是@InjectAws(S3Client)注入的并非S3Client类本身,而是aws-sdk-v3-nest模块内部生成的自定义注入token,直接override S3Client provider无法匹配到实际的注入目标。
解决步骤
- 导入
aws-sdk-v3-nest提供的getAwsClientToken函数,用于获取@InjectAws实际使用的注入token - 使用该token覆盖对应provider,替换为mock的S3客户端实例
- 结合
aws-sdk-client-mock的mockClient配置预期行为,并在测试周期内维护mock状态
修改后的测试代码
import { S3Client } from '@aws-sdk/client-s3'; import { mockClient } from 'aws-sdk-client-mock'; import { getAwsClientToken } from 'aws-sdk-v3-nest'; import { Test } from '@nestjs/testing'; import { AppModule } from './app.module'; const s3Mock = mockClient(S3Client); describe('InvoicesController (e2e)', () => { let app: INestApplication; beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }) // 使用正确的注入token覆盖S3客户端 .overrideProvider(getAwsClientToken(S3Client)) .useValue(s3Mock) .compile(); app = moduleFixture.createNestApplication(); await app.init(); }); beforeEach(() => { // 重置mock状态,避免测试用例间的污染 s3Mock.reset(); }); afterAll(async () => { await app.close(); }); // 示例测试用例 it('should trigger mocked S3 operation', async () => { // 配置mock的响应结果 s3Mock.onAnyCommand().resolves({ // 模拟S3接口返回数据,比如PutObjectCommand的响应 ETag: 'mock-etag', }); // 执行测试逻辑:调用依赖S3fileService的接口 // const response = await request(app.getHttpServer()).post('/your-endpoint').send(...); // 断言接口响应或mock调用情况 // expect(s3Mock.calls()).toHaveLength(1); }); });
关键说明
getAwsClientToken(S3Client)返回的是aws-sdk-v3-nest注册S3客户端时使用的唯一标识,与@InjectAws(S3Client)的注入目标完全匹配,确保override生效- 每次测试前执行
s3Mock.reset(),可以清空mock的调用记录和已配置的响应规则,保证测试用例独立性 - 若需要验证S3方法的调用细节,可通过
s3Mock.calls()获取调用记录,断言调用次数、参数等
内容的提问来源于stack exchange,提问作者AlexanderT
相关产品推荐
相关产品推荐

