Nestjs Repository单元测试报错:Received promise resolved instead of rejected
NestJS TypeORM 自定义Repository单元测试(条目不存在场景)问题
问题背景
在为后端应用编写单元测试,测试数据库中不存在对应条目的场景时遇到问题。
待测试Repository代码
@EntityRepository(Collectible) export class CollectibleRepository extends Repository<Collectible> { async getCollectible(id: number) { const collectible = await this.findOne(id); if (!collectible) { throw new NotFoundException(); } return collectible; } }
初始测试代码(出错用例)
const mockCollectible = new Collectible( faker.lorem.sentence(), faker.lorem.sentences(3), faker.datatype.float(), faker.datatype.float(), faker.datatype.number(), ); describe('Collectible Repository', () => { let collectibleRepository: CollectibleRepository; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [CollectibleRepository], }).compile(); collectibleRepository = module.get<CollectibleRepository>( CollectibleRepository, ); }); describe('View Collectibles', () => { it('throws and error as the collectible is not found', async (done) => { collectibleRepository.findOne = jest.fn().mockResolvedValue(undefined); await expect(collectibleRepository.getCollectible(1)).rejects.toThrow( NotFoundException, ); done(); }); }); });
首次运行报错信息
Expected message: not "Not Found" 8 | const collectible = await this.findOne(id, { relations: ['business'] }); 9 | if (!collectible) { > 10 | throw new NotFoundException(); | ^ 11 | } 12 | return collectible; 13 | } at CollectibleRepository.getCollectibleBusiness (src/collectible/collectible.repository.ts:10:13) (Use `node --trace-warnings ...` to show where the warning was created) (node:95012) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict`. (rejection id: 3) (node:95012) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. FAIL src/collectible/collectible.repository.spec.ts (8.525 s) ● Collectible Repository › View Collectibles › throws and error as the collectible is not found expect(received).rejects.not.toThrow() Received promise resolved instead of rejected Resolved to value: undefined 39 | it('throws and error as the collectible is not found', async (done) => { 40 | collectibleRepository.findOne = jest.fn().mockResolvedValue(undefined); > 41 | await expect(collectibleRepository.getCollectible(1)).rejects.not.toThrow( | ^ 42 | NotFoundException, 43 | ); 44 | done(); at expect (../node_modules/expect/build/index.js:134:15) at Object.<anonymous> (collectible/collectible.repository.spec.ts:41:13)
排查与更新进展
- 首次排查参考NestJS测试示例仓库,未找到直接测试自定义Repository的相关内容
- 修正代码中缺失的await、调用错误函数的问题后,出现新警告:
(node:98378) UnhandledPromiseRejectionWarning: Error: expect(received).rejects.not.toThrow(expected)
- 后续确认该警告由其他测试用例导致,可暂时搁置
解决方案
核心错误原因
- 断言逻辑写反:测试代码中多写了
.not,原本预期抛出异常,错误写成了预期不抛出异常 - 异步逻辑处理不当:混用async/await和done回调,导致异步异常没有被正确捕获
修正后测试用例
it('should throw NotFoundException when collectible does not exist', async () => { // 模拟findOne返回空,代表未查询到对应条目 jest.spyOn(collectibleRepository, 'findOne').mockResolvedValue(undefined); // 直接断言方法会抛出NotFoundException await expect(collectibleRepository.getCollectible(1)).rejects.toThrow(NotFoundException); });
优化建议
- 优先使用
jest.spyOn模拟类方法,而非直接给方法赋值mock,方便后续恢复原方法实现 - 异步测试用例中不需要额外使用done回调,Jest会自动等待async函数的所有异步逻辑执行完成
内容的提问来源于stack exchange,提问作者Jeremy
相关产品推荐
相关产品推荐

