如何正确测试查询函数逻辑?验证findOne及QueryBuilder配置
如何测试TypeORM查询的关联、连接与条件配置?
针对你提供的两个查询函数,我们可以通过验证TypeORM Repository/QueryBuilder的调用参数来确保查询配置正确,而非仅模拟返回结果。以下是具体测试方案:
一、测试findOne函数(基础查询配置)
该函数直接调用repo.findOne,我们可以通过Mock Repository,断言它被调用时传入的where和relations参数是否符合预期:
测试代码示例(Jest)
import { YourService } from './your-service'; import { Repository } from 'typeorm'; describe('YourService.findOne', () => { let service: YourService; let mockRepo: jest.Mocked<Repository<any>>; beforeEach(() => { // 初始化Mock Repository mockRepo = { findOne: jest.fn().mockResolvedValue({ id: 'test-id', foo: {}, bar: {} }) } as any; // 假设服务通过构造函数注入Repository service = new YourService(mockRepo); }); it('应该指定正确的查询条件和关联关系', async () => { const testId = 'test-id'; await service.findOne(testId); // 断言findOne的调用参数完全符合预期 expect(mockRepo.findOne).toHaveBeenCalledWith({ where: { id: testId }, relations: ['foo', 'bar'] }); }); });
二、测试findAnotherOne函数(QueryBuilder链式调用)
对于QueryBuilder的链式调用,我们需要MockcreateQueryBuilder,并跟踪每个链式方法的调用参数,确保select、where、leftJoin的配置都正确:
测试代码示例(Jest)
describe('YourService.findAnotherOne', () => { let service: YourService; let mockRepo: jest.Mocked<Repository<any>>; let mockQueryBuilder: any; beforeEach(() => { // 初始化Mock QueryBuilder,每个方法返回自身以支持链式调用 mockQueryBuilder = { select: jest.fn().mockReturnThis(), where: jest.fn().mockReturnThis(), leftJoin: jest.fn().mockReturnThis(), getOne: jest.fn().mockResolvedValue({ id: 'test-bar-id' }) }; // 让Repository的createQueryBuilder返回Mock QueryBuilder mockRepo = { createQueryBuilder: jest.fn().mockReturnValue(mockQueryBuilder) } as any; service = new YourService(mockRepo); }); it('应该正确构建查询:指定select字段、where条件和leftJoin关联', async () => { const testId = 'test-id'; await service.findAnotherOne(testId); // 断言createQueryBuilder使用了正确的别名 expect(mockRepo.createQueryBuilder).toHaveBeenCalledWith('foo'); // 断言select指定了正确字段 expect(mockQueryBuilder.select).toHaveBeenCalledWith('bar.id'); // 断言where条件和参数绑定正确 expect(mockQueryBuilder.where).toHaveBeenCalledWith('id = :id', { id: testId }); // 断言leftJoin的关联关系正确 expect(mockQueryBuilder.leftJoin).toHaveBeenCalledWith('foo.bar', 'bar'); // 断言最终调用了getOne获取结果 expect(mockQueryBuilder.getOne).toHaveBeenCalled(); }); });
为什么不能只模拟返回值?
如果仅MockgetOne或findOne的返回结果,后续即使有人修改了查询配置(比如删除relations、修改leftJoin关联、更改where条件),测试依然会通过,但实际运行时会返回错误数据。而上述方案直接验证查询的构建过程,能确保代码的查询逻辑始终符合预期。
内容的提问来源于stack exchange,提问作者aProgger
相关产品推荐
相关产品推荐

