如何使用 Jest 在 TypeORM 中存根 EntityManager 和 Connection

Posted

技术标签:

【中文标题】如何使用 Jest 在 TypeORM 中存根 EntityManager 和 Connection【英文标题】:How to stub EntityManager and Connection in TypeORM with Jest 【发布时间】:2020-08-21 13:11:35 【问题描述】:

我在 Typescript 中使用 TypeORM 和用 Jest 编写的单元测试获得了一个关于 NestJS 的应用程序。我有一个使用这样的事务的函数:

async createMany(users: User[]) 
  await this.connection.transaction(async manager => 
    await manager.save(users[0]);
    await manager.save(users[1]);
  );

这是 NestJS 文档中的一个示例。我通过this.connection.transaction 以大致相同的方式执行此操作,但业务逻辑不同。

问题是我想做一个单元测试来测试这个服务功能。所以我需要以某种方式模拟this.connection 和它的manager。或者至少是经理。我不确定如何使用 Jest 来做到这一点。我无法在没有连接的情况下创建经理。我无法在没有经理返回的情况下创建模拟连接。

同时使用 TypeORM 和 Jest 是 NestJS 的标准。必须有一种方法来编写带有事务的单元测试。但我不知道该怎么做。

请注意,我问的是单元测试模拟 ORM。不是直接使用测试数据库实例的集成测试。

【问题讨论】:

【参考方案1】:

您需要使用模拟的Connection 创建一个TestingModule。像这样的东西:

import  Test  from "@nestjs/testing";

describe("UsersService", () => 
    let usersService;
    let connection;
    const mockConnection = () => (
        transaction: jest.fn()
    );

    beforeEach(async () => 
        const module = await Test.createTestingModule(
            providers: [
                UsersService,
                
                    provide: Connection,
                    useFactory: mockConnection
                
            ],
        ).compile();

        usersService = await module.get<UsersService>(UsersService); 
        connection = await modle.get<Connection>(Connection);
    );

    describe("some tests", () => 
        it("should test something", async () => 
            const someMockedUsers = [/* some users */];
            const mockedManager = 
                save: jest.fn()
            
            connection.transaction.mockImplementation((cb) => 
                cb(mockedManager);
            );

            await userService.createMany(someMockedUsers);

            expect(connection.transaction).toHaveBeenCalled();
            expect(mockedManager.save).toHaveBeenCalledTimes(2);
            // ...

        );
    );


);

【讨论】:

这应该可以。然而,使用Test.createTestingModule 给我带来了很多占用大量 RAM 的问题。我最终没有使用它并转而使用sinon.js @kkkkkkkk 您的解决方案效果很好,谢谢!我没有得到一些东西,当我期望调用连接时,我得到一个错误。即使正确调用了模拟。你知道为什么 jest 不会记录电话等吗?【参考方案2】:

我相信你也可以:

import  getConnectionToken  from '@nestjs/typeorm';


  provide: getConnectionToken(),
  useClass: Connection,
,

【讨论】:

在您的代码之后遇到此错误,TypeError: Cannot read properties of undefined (reading 'name') at new Connection (connection/Connection.ts:119:29)

以上是关于如何使用 Jest 在 TypeORM 中存根 EntityManager 和 Connection的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Jest 对 typeorm getRepository 进行单元测试?

如何修复预期值:“1”接收到的数组:[“COUNT (*)”:“1”] 在带有 jest 框架的 TypeORM 中出现错误

如何使用 Jest 和 Proxyquire 存根模块?

如何修复预期值:“1”收到的数组:带有jest框架的TypeORM中的[{“COUNT(*)”:“1”}]错误

如何用 Jest 单元测试覆盖 TypeORM @Column 装饰器?

使用 TypeORM 和 Nestjs 进行测试的过程,以及使用 mocks 的玩笑?