You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确测试查询函数逻辑?验证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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:40:28