【问题标题】:NestJS Unit Testing of the Service: Mocking getManager resulting in 'Connection "default" was not found' error服务的 NestJS 单元测试:模拟 getManager 导致“未找到连接“默认””错误
【发布时间】:2021-08-04 07:04:36
【问题描述】:

我目前正在对我的 NestJS 服务进行单元测试。我的实体称为“用户”,我建立了一个基本服务,允许我与 MS SQL 服务器交互,并在我的控制器中建立 GET 和 POST 端点。

我试图模拟的服务方法之一是deleteV2 函数,您可以在下面找到它:


// service file 
import { Injectable } from '@nestjs/common';
import { InjectConnection, InjectEntityManager, InjectRepository } from '@nestjs/typeorm';
import { Connection, createConnection, EntityManager, getConnection, getManager, getRepository, Repository } from "typeorm";
import {User} from '../entities/user.entity';


@Injectable()
export class ServiceName {
  constructor(@InjectRepository(User) private usersRepository: Repository<User>,
              @InjectConnection() private connection: Connection,
              @InjectEntityManager() private manager: EntityManager
              ) {}

  async delete(id: number): Promise<any> {
    return await this.manager.delete(User, id);
  }
  async deleteV2(id: number): Promise<any> {
    return await getManager().delete(User, id);
  }

请注意,我导入EntityManager 并在我的服务中注入(使用@InjectEntityManager()manager: EntityManager 的原因很简单,因为我想要更多练习使用不同的方法(我是一名新实习生与 NestJS 一起工作)。事实上,我在使用注入的manager 的地方定义了delete 方法,然后在我使用导入的getManager 的地方定义了deleteV2 方法,这也是以不同方式练习单元测试的纯粹原因。而我注入Repository、Connection、EntityManager,也是出于同样的原因。

在我的 spec.ts 服务单元测试文件中,我有:

// unit testing file for the service

type MockType<T> = { 
    [P in keyof T]?: jest.Mock<{}>;
};

describe('service tests', () => {
    const mockManagerFactory = jest.fn(() => ({
        delete: jest.fn().mockReturnValue(undefined),
    }))
 
    let service: ServiceName;
    // mock repository and mock connection also defined similarly to mockManager
    let mockManager: MockType<EntityManager>; 

    beforeEach(async () => {     
        const module: TestingModule = await Test.createTestingModule({
            providers: [
                ServiceName,
                // tokens for Repository and Connection are also provided along with their respective Factories
                {
                    provide: getEntityManagerToken(),
                    useFactory: mockManagerFactory,
                },
            ],
        }).compile();

        service = module.get<ServiceName>(ServiceName);
        // mockRepository and mockConnection also defined but not shown
        mockManager = module.get(getEntityManagerToken());
    });
})

在同一个 spec.ts 文件中,我定义了多个测试。引起问题的是下面涉及deleteV2的问题:

// same unit testing file for the service 
         
        // first test
        it('first test', async () => {
            expect(await service.delete(1000)).toEqual(undefined);
            expect(mockManager.delete).toBeCalled();
        });
        
        // second test 
        it('second test', async () => {
            expect(await service.deleteV2(1000)).toEqual(undefined);
            expect(mockManager.delete).toBeCalled();
        })

虽然第一个测试运行没有问题(第一个测试与服务文件中的delete关联),但第二个测试(与服务文件中的deleteV2关联)没有通过并导致以下错误:

● service tests › Service Functions › second test

ConnectionNotFoundError: Connection "default" was not found.

      at new ConnectionNotFoundError (error/ConnectionNotFoundError.ts:8:9)
      at ConnectionManager.Object.<anonymous>.ConnectionManager.get (connection/ConnectionManager.ts:40:19)
      at Object.getManager (index.ts:260:35)

任何想法如何处理这个错误?似乎提供getEntityManagerToken() 与注入的manager 一起使用,但不适用于导入的getManager,因为deleteV2 使用getManagerdelete(通过测试)使用导入的manager

【问题讨论】:

    标签: typescript nestjs


    【解决方案1】:

    这就是使用依赖注入的巨大好处所在。@InjectEntityManager() 只是注入(理论上)已经为您设置了连接的对象,您可以使用这些方法而不用担心连接。它使测试变得更加容易(在我看来)。使用getMananger(),您必须担心 TypeORM 会尝试从当前活动连接中获取实体管理器,而这在测试中不应该存在。您可以使用jest 模拟它,使用类似以下的内容

    const deleteMock = jest.fn();
    jest.mock('typeorm', () => ({
      getManager: () => ({
        delete: deleteMock,
      })
    }))
    

    这很好用,但如果可能的话,我会避免直接从 TypeORM 调用 getConnectiongetManager 之类的方法。

    【讨论】:

    • 看起来不错,但请告诉我如何模拟 @InjectEntityManager()
    猜你喜欢
    • 2021-08-03
    • 2020-02-13
    • 2020-03-22
    • 1970-01-01
    • 2019-11-04
    • 1970-01-01
    • 2019-11-22
    • 2019-06-04
    • 1970-01-01
    相关资源
    最近更新 更多