Jest单元测试中TypeScript类getItem方法catch代码块测试失败求助
从你的描述来看,代码确实进入了catch块并打印了日志,但测试断言失败提示“未抛出错误”,这看起来矛盾,下面是几个针对性的排查方向和解决方案:
1. 调整Jest的错误断言方式
当你使用.rejects.toThrowError(dummyAWSError)时,Jest会尝试严格匹配错误对象的引用。如果实际抛出的错误和你定义的dummyAWSError不是同一个引用(比如被底层逻辑包装过),断言就会失败。
你可以改为匹配错误的消息内容,这种方式更可靠:
await expect(repository.getItem(key)).rejects.toThrowError('AWS can not be reached')
或者使用.toThrow方法,它对错误对象的匹配逻辑更宽松:
await expect(repository.getItem(key)).rejects.toThrow(dummyAWSError)
2. 验证错误是否真的被传播
虽然你的getItem方法逻辑上会在catch块抛出错误,但可以临时在测试中手动捕获错误,验证是否能正确拿到:
test('it should throw the AWS Error when getting item from DynamoDB', async () => { documentClient.get = jest.fn().mockReturnValue({ promise: jest.fn().mockRejectedValue(dummyAWSError) }) // 手动捕获错误,确认是否存在 let caughtError: AWSError | undefined; try { await repository.getItem(key); } catch (err) { caughtError = err as AWSError; console.log("测试捕获到的错误:", err); } expect(caughtError).toBeDefined(); expect(caughtError?.message).toBe('AWS can not be reached'); // 再运行原断言 await expect(repository.getItem(key)).rejects.toThrowError('AWS can not be reached'); })
如果手动捕获能拿到错误,说明问题出在Jest的断言匹配上;如果拿不到,需要检查getItem的错误传播逻辑是否被意外拦截。
3. 确保Mock的documentClient是实例使用的对象
如果你的repository类是在内部创建documentClient实例(比如构造函数中this.documentClient = new DocumentClient()),那么测试中修改全局的documentClient不会影响到repository实例中的对象。
解决方法是使用依赖注入:让repository的构造函数接受documentClient参数,测试时传入Mock对象:
// 修改repository类的构造函数 constructor(private readonly documentClient: DocumentClient, private readonly tableName: string) {} // 测试中创建Mock并注入 const mockDocumentClient = { get: jest.fn().mockReturnValue({ promise: jest.fn().mockRejectedValue(dummyAWSError) }) }; const repository = new YourRepository(mockDocumentClient, 'test-table');
这样能确保repository使用的是你Mock的documentClient,避免Mock失效。
4. 修复getItem方法的返回值(可选但重要)
虽然这不是测试失败的直接原因,但你的getItem方法在成功时没有返回实际的Item,会导致成功时返回undefined,不符合方法的返回类型声明。建议修改:
protected async getItem (key: DocumentClient.Key, consistentRead?: boolean): Promise<Item | undefined> { const dynamoDbResult = await this.documentClient.get({ Key: key, TableName: this.tableName, ConsistentRead: consistentRead }).promise().catch(error => { this.logAWSError('Failed to get an item from the DynamoDb', error) throw error }); // 返回DynamoDB结果中的Item字段 return dynamoDbResult.Item; }
内容的提问来源于stack exchange,提问作者Softengilker

