Jest中AWS SDK v3单元测试Mock跨describe块无法重置的问题
在不同describe测试块中重置aws-sdk-client-mock的解决方案
问题场景
我在对Lambda函数进行单元测试时,使用aws-sdk-client-mock库实现Mock功能。测试Lambda的5xx状态码时,需要移除Mock以触发凭证错误(CredentialsProviderError: Could not load credentials from any providers),但第一个describe块的Mock仍处于活跃状态,导致第二个测试用例无法正常执行。只有注释掉第一个describe块(完全不使用Mock)时,第二个测试才能正常运行。
原始测试代码如下:
import { APIGatewayProxyResult } from 'aws-lambda'; import { main } from "../../lib/src/lambda/approval-handler"; import { mockClient } from "aws-sdk-client-mock"; import { CodePipelineClient } from "@aws-sdk/client-codepipeline"; import { event, queryStringParameters } from "../utils/lambda-event" describe("Successful Approve or Deny", () => { // 此测试正常运行 const pipelineClientMock = mockClient(CodePipelineClient); beforeEach(() => { pipelineClientMock.reset(); }); it("returns a 301 response with a redirect location if all required query parameters are provided", async () => { pipelineClientMock.resolves({}) const result: APIGatewayProxyResult = await main(event); expect(result.statusCode).toEqual(301); }); }) describe("When Approval or Deny is not sent successfully", () => { // 此测试失败,因为Mock仍活跃 it("returns a 502 error response if any of the required query parameters are missing", async () => { const result: APIGatewayProxyResult = await main(event); expect(result.statusCode).toEqual(502); }); });
解决方法
aws-sdk-client-mock创建的Mock是全局生效的,reset()方法仅能重置Mock的调用记录和预设逻辑,无法销毁Mock本身。要彻底移除Mock,需要在测试块结束时调用restore()方法。
1. 在第一个测试块中添加afterAll钩子销毁Mock
修改第一个describe块,在测试全部结束后调用restore(),彻底销毁Mock,让后续测试块能使用真实的客户端逻辑:
describe("Successful Approve or Deny", () => { const pipelineClientMock = mockClient(CodePipelineClient); beforeEach(() => { pipelineClientMock.reset(); }); // 测试块结束后销毁Mock afterAll(() => { pipelineClientMock.restore(); }); it("returns a 301 response with a redirect location if all required query parameters are provided", async () => { pipelineClientMock.resolves({}) const result: APIGatewayProxyResult = await main(event); expect(result.statusCode).toEqual(301); }); })
2. 确保第二个测试块不创建Mock
第二个测试块不需要任何Mock配置,直接执行测试逻辑即可。此时调用CodePipelineClient会因为没有凭证抛出预期的错误,进而触发Lambda返回5xx状态码的逻辑。
扩展:多测试块的Mock隔离方案
如果后续还有需要使用Mock的测试块,可以遵循每个测试块独立创建和销毁Mock的原则:
- 在
beforeAll中创建Mock - 在
afterAll中调用restore()销毁Mock - 在
beforeEach中调用reset()重置Mock状态
这样就能保证每个测试块的Mock互不干扰。
内容的提问来源于stack exchange,提问作者Jatin Mehrotra
相关产品推荐
相关产品推荐

