如何在Jest中mock .then()与.catch()?AWS Cognito场景测试问题
报错原因
你遇到的TypeError: cognito.signUp(...).then(...).catch is not a function报错,核心是cognito.signUp()调用后经过.then()返回的不是Promise实例,只有Promise类型才支持链式调用.catch()方法。绝大多数情况是你对signUp的mock不符合实际返回规则:要么signUp没返回Promise,要么你单独mock了.then方法但返回了普通值而非Promise。
解决示例
分两种常见的AWS Cognito调用场景给出mock方案:
场景1:业务代码直接调用signUp().then().catch
如果你的业务代码中signUp本身返回Promise,写法如下:
// 业务代码示例 export const registerUser = (userData) => { return cognito.signUp({ ClientId: process.env.COGNITO_CLIENT_ID, Username: userData.phone, Password: userData.password }) .then(res => { // 你的then块逻辑 return { success: true, data: res } }) .catch(err => { // 你的catch块逻辑 return { success: false, error: err.message } }) }
对应的Jest测试代码:
import { registerUser } from './your-auth-file' import cognito from './cognito-instance' // mock cognito实例的signUp方法 jest.mock('./cognito-instance', () => ({ signUp: jest.fn() })) // 测试.then分支逻辑 it('handles signUp success correctly', async () => { // mock signUp返回resolve状态的Promise,触发then逻辑 const mockSuccessRes = { UserSub: 'test-123', UserConfirmed: false } cognito.signUp.mockResolvedValueOnce(mockSuccessRes) const result = await registerUser({ phone: '13800000000', password: 'Test@1234' }) expect(result.success).toBe(true) expect(result.data).toEqual(mockSuccessRes) }) // 测试.catch分支逻辑 it('handles signUp error correctly', async () => { // mock signUp返回reject状态的Promise,触发catch逻辑 const mockError = new Error('Username already exists') cognito.signUp.mockRejectedValueOnce(mockError) const result = await registerUser({ phone: '13800000000', password: 'Test@1234' }) expect(result.success).toBe(false) expect(result.error).toBe('Username already exists') })
场景2:业务代码使用signUp().promise().then().catch(AWS SDK v2标准写法)
AWS SDK v2中调用服务方法默认返回AWS.Request对象,需要手动调用.promise()才会返回Promise,对应写法如下:
// 业务代码示例 export const registerUser = (userData) => { return cognito.signUp({ ClientId: process.env.COGNITO_CLIENT_ID, Username: userData.phone, Password: userData.password }) .promise() .then(res => { return { success: true, data: res } }) .catch(err => { return { success: false, error: err.message } }) }
对应的Jest测试代码:
import { registerUser } from './your-auth-file' import cognito from './cognito-instance' jest.mock('./cognito-instance', () => ({ signUp: jest.fn() })) // 测试.then分支逻辑 it('handles signUp success correctly', async () => { const mockSuccessRes = { UserSub: 'test-123', UserConfirmed: false } // mock signUp返回带promise方法的对象,promise方法返回resolve状态的Promise cognito.signUp.mockReturnValueOnce({ promise: jest.fn().mockResolvedValueOnce(mockSuccessRes) }) const result = await registerUser({ phone: '13800000000', password: 'Test@1234' }) expect(result.success).toBe(true) expect(result.data).toEqual(mockSuccessRes) }) // 测试.catch分支逻辑 it('handles signUp error correctly', async () => { const mockError = new Error('Password does not meet policy requirements') cognito.signUp.mockReturnValueOnce({ promise: jest.fn().mockRejectedValueOnce(mockError) }) const result = await registerUser({ phone: '13800000000', password: '123' }) expect(result.success).toBe(false) expect(result.error).toBe('Password does not meet policy requirements') })
注意点
不要单独mocksignUp的.then方法,必须保证signUp的返回值是完整的Promise实例,否则链式调用.catch必然报错。如果你是全局mock AWS SDK,要保证CognitoIdentityServiceProvider实例的调用路径和业务代码完全一致,避免mock失效。
内容的提问来源于stack exchange,提问作者Raja Sardar
相关产品推荐
相关产品推荐

