繁体   English   中英

如何模拟 typeorm 连接

[英]How to mock typeorm connection

在集成测试中,我使用以下代码段来创建连接

import {Connection, createConnection} from 'typeorm';
// @ts-ignore
import options from './../../../ormconfig.js';

export function connectDb() {
  let con: Connection;

  beforeAll(async () => {
    con = await createConnection(options);
  });

  afterAll(async () => {
    await con.close();
  });

}

我正在尝试对一个类进行单元测试,该类在其方法之一中调用typeorm 存储库,并且没有调用上面的帮助函数connectDb()我得到以下错误,这当然是预期的。

ConnectionNotFoundError:未找到连接“默认”。

我的问题是如何模拟连接。 我已经尝试了以下没有任何成功

import typeorm, {createConnection} from 'typeorm';
// @ts-ignore
import options from "./../../../ormconfig.js";

const mockedTypeorm = typeorm as jest.Mocked<typeof typeorm>;

jest.mock('typeorm');

 beforeEach(() => {
    //mockedTypeorm.createConnection.mockImplementation(() => createConnection(options)); //Failed
    mockedTypeorm.createConnection = jest.fn().mockImplementation(() => typeorm.Connection);

    MethodRepository.prototype.changeMethod = jest.fn().mockImplementation(() => {
      return true;
    });
  });

使用这种模拟运行测试会出现此错误

类型错误:装饰器不是函数

注意:如果我在测试中调用 connectDb() 一切正常。 但我不想这样做,因为在运行任何测试之前将某些数据插入数据库需要太多时间。 为简单起见,省略了一些代码。 任何帮助将不胜感激

经过大量的研究和实验,我最终得到了这个解决方案。 我希望它适用于遇到同样问题的其他人......

  • 它不需要任何数据库连接
  • 测试服务层内容,而不是数据库层本身
  • test 可以轻松涵盖我需要测试的所有情况,我只需要为相关的 typeorm 方法提供正确的输出。

这是我要测试的方法

@Injectable()
export class TemplatesService {
  constructor(private readonly templatesRepository: TemplatesRepository) {}

  async list(filter: ListTemplatesReqDTO) {
    const qb = this.templatesRepository.createQueryBuilder("tl");
    const { searchQuery, ...otherFilters } = filter;
    if (filter.languages) {
      qb.where("tl.language IN (:...languages)");
    }
    if (filter.templateTypes) {
      qb.where("tl.templateType IN (:...templateTypes)");
    }
    if (searchQuery) {
      qb.where("tl.name LIKE :searchQuery", { searchQuery: `%${searchQuery}%` });
    }
    if (filter.skip) {
      qb.skip(filter.skip);
    }
    if (filter.take) {
      qb.take(filter.take);
    }
    if (filter.sort) {
      qb.orderBy(filter.sort, filter.order === "ASC" ? "ASC" : "DESC");
    }
    return qb.setParameters(otherFilters).getManyAndCount();
  }

...
}

这是测试:

import { SinonStub, createSandbox, restore, stub } from "sinon";
import * as typeorm from "typeorm";

describe("TemplatesService", () => {
  let service: TemplatesService;
  let repo: TemplatesRepository;

  const sandbox = createSandbox();
  const connectionStub = sandbox.createStubInstance(typeorm.Connection);
  const templatesRepoStub = sandbox.createStubInstance(TemplatesRepository);
  const queryBuilderStub = sandbox.createStubInstance(typeorm.SelectQueryBuilder);
  stub(typeorm, "createConnection").resolves((connectionStub as unknown) as typeorm.Connection);
  connectionStub.getCustomRepository
    .withArgs(TemplatesRepository)
    .returns((templatesRepoStub as unknown) as TemplatesRepository);

  beforeAll(async () => {
    const builder: TestingModuleBuilder = Test.createTestingModule({
      imports: [
        TypeOrmModule.forRoot({
          type: "postgres",
          database: "test",
          entities: [Template],
          synchronize: true,
          dropSchema: true
        })
      ],
      providers: [ApiGuard, TemplatesService, TemplatesRepository],
      controllers: []
    });
    const module = await builder.compile();

    service = module.get<TemplatesService>(TemplatesService);
    repo = module.get<TemplatesRepository>(TemplatesRepository);
  });

  beforeEach(async () => {
    // do something
  });

  afterEach(() => {
    sandbox.restore();
    restore();
  });

  it("Service should be defined", () => {
    expect(service).toBeDefined();
  });


  describe("list", () => {
    let fakeCreateQueryBuilder;

    it("should return records", async () => {
      stub(queryBuilderStub, "skip" as any).returnsThis();
      stub(queryBuilderStub, "take" as any).returnsThis();
      stub(queryBuilderStub, "sort" as any).returnsThis();
      stub(queryBuilderStub, "setParameters" as any).returnsThis();
      stub(queryBuilderStub, "getManyAndCount" as any).resolves([
        templatesRepoMocksListSuccess,
        templatesRepoMocksListSuccess.length
      ]);
      fakeCreateQueryBuilder = stub(repo, "createQueryBuilder" as any).returns(queryBuilderStub);
      const [items, totalCount] = await service.list({});

      expect(fakeCreateQueryBuilder.calledOnce).toBe(true);
      expect(fakeCreateQueryBuilder.calledOnce).toBe(true);
      expect(items.length).toBeGreaterThan(0);
      expect(totalCount).toBeGreaterThan(0);
    });
  });
});

干杯!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM