在单元测试中Jest模拟Typeorm数据源(没有nestjs)

问题描述 投票:0回答:1

我正在为一个使用 Typeorm 而不使用 Nestjs 的项目创建单元测试。我正在为其创建单元测试的文件使用 queryRunner 来启动事务。我的问题是,我无法模拟数据源。我尝试了多种方法,但从未调用模拟来替换可以访问 postgresql 数据库的实际数据源。我看到了一些模拟它的解决方案,但它们都使用 Nestjs,我在我的例子中没有使用它。

我现在在测试中遇到的错误是:

    Received promise rejected instead of resolved
    Rejected to value: [TypeORMError: Driver not Connected]

任何帮助将不胜感激,因为我不是单元测试方面的专家。

这是我遇到问题的代码示例(替换了一些名称):

datasource.ts

//database config is defined in this file
export const datasource: DataSource = new DataSource(some_config);

dummy.service.ts

export const dummyService = () => {
    //datasource is imported from the above file
    const queryRunner = datasource.createQueryRunner();
    await queryRunner.startTransaction();

    try {
      const foundObject = await queryRunner.manager.getRepository(MyObject).findOne({
        where: { id: someId },
        lock: { mode: 'pessimistic_write' },
      });
      //some more database calls
    } catch (error) {
      await queryRunner.rollbackTransaction();
    } finally {
      await queryRunner.release();
    }
}

mock.datasource.ts

import { DataSource } from 'typeorm';

export const dataSourceMockFactory: () => MockType<DataSource> = jest.fn(
  () => ({
    createQueryRunner: jest.fn().mockImplementation(() => ({
      connect: jest.fn(),
      startTransaction: jest.fn(),
      release: jest.fn(),
      rollbackTransaction: jest.fn(),
      manager: {
        getRepository: jest.fn().mockImplementation(() => ({
          create: jest.fn(),
          findOne: jest.fn(() => {
            return getMyDummyObject();
          }),
        })),
        save: jest.fn(),
      },
    })),
  }),
);

export type MockType<T> = {
  // eslint-disable-next-line @typescript-eslint/ban-types
  [P in keyof T]?: jest.Mock<{}>;
};

dummy.unit.test.ts

describe('dummy service test', () => {
  let dataSourceMock: MockType<Typeorm.DataSource>;

  beforeEach(async () => {

    // This method did not work
    jest.mock('typeorm', () => {
      const actual = jest.requireActual('typeorm');
      return {
        ...actual,
        DataSource: dataSourceMockFactory(),
      };
    });

    // The below method did not work either
    jest.mock('./../../db/datasource', () => ({
      datasource: dataSourceMockFactory(),
    }));
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should test dummy service with transaction', async () => {
    // getting an error here
    await expect(
      dummyFunction(),
    ).resolves.not.toThrow();
  });

});

postgresql unit-testing jestjs typeorm ts-jest
1个回答
0
投票

您可以使用内存中的sqlite数据库:

const options: ConnectionOptions = {
  type: "sqlite",
  database: "memory",
  entities: [ User, Message ],
  logging: true
}

用它来调用 createConnection,并在测试中使用该连接

快速,比模拟更好,并且对于单元测试来说“足够相似”。不过,仍然需要对 postgres 进行集成测试。

如果您依赖于数据库特定的功能,还有像 pg-mem 这样的东西:

https://github.com/oguimbal/pg-mem

© www.soinside.com 2019 - 2024. All rights reserved.