簡體   English   中英

使用 NestJS 服務單元測試未找到連接“默認”

[英]Connection "default" was not found with NestJS Unit Testing of Service

我目前正在對我的 NestJS 服務進行單元測試。 我的實體稱為“用戶”,我建立了一個基本服務,允許我與 MS SQL 服務器交互,並在我的 Controller 中建立 GET 和 POST 端點。

雖然我能夠模擬服務中使用的Repository ,但我無法在必須調用getConection()的方法中建立模擬getConnection

當我嘗試使用npm run test:watch單元測試時,我收到ConnectionNotFoundError: Connection "default" was not found. 我已經研究過(實際上,從中得到了很多) How to stub EntityManager and Connection in TypeORM with Jest ,但這篇文章似乎沒有詳細說明未建立的連接,這是我的問題。

無論如何,這是我對相關部分的服務:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { getConnection, Repository } from "typeorm";
import {User} from '../entities/user.entity';


@Injectable()
export class ServiceName {
  constructor(@InjectRepository(User) private usersRepository: Repository<User>) {}

  // Creating and inserting a new user into the database table using Repository
  // unit testing for this one works fine
  async createUserRepository(user: User): Promise<User> {
    const newUser = this.usersRepository.create(user); 
    return await this.usersRepository.save(newUser);
  }

  // Creating and inserting a new user into the database table using QueryBuilder and getConnection
  // unit testing for this one does not work so well 
  async createUserQueryBuilder(user: User): Promise<User> {
    await getConnection()
    .createQueryBuilder()
    .insert()
    .into(User)
    .values([
        user, 
     ])
    .execute();
    return user;  
  }

這是我用於單元測試的 spec.ts 文件:

import { Test, TestingModule } from '@nestjs/testing';
import { ServiceName } from './app_codes_rms_area.service';
import { getRepositoryToken } from '@nestjs/typeorm';
import { User } from '../entities/user.entity';
import { Connection, Repository } from 'typeorm';

describe('service tests', () => {

    const repositoryMockFactory: () => MockType<Repository<any>> = jest.fn(() => ({ 
        create: jest.fn(),
        save: jest.fn(),
        // other functions
    }));

    const mockConnectionFactory = jest.fn(() => ({
        getConnection: jest.fn().mockReturnValue({
            createQueryBuilder: jest.fn().mockReturnThis(),
            getMany: jest.fn().mockReturnValue(allUsers),
            insert: jest.fn().mockReturnThis(),
            into: jest.fn().mockReturnThis(),
            values: jest.fn().mockReturnThis(),
            execute: jest.fn().mockReturnValue(user),
        })
    }));
 
    let service: ServiceName;
    let mockRepository: MockType<Repository<User>>;
    let mockConnection: Connection;

    beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            providers: [
                ServiceName,
                {
                    provide: getRepositoryToken(User), // a User Repository is injected to the service 
                    useFactory: repositoryMockFactory, // using factory ensures that a new mock is used for every test
                },
                {
                    provide: Connection,
                    useFactory: mockConnectionFactory,
                }
            ],
        }).compile();

        service = module.get<ServiceName>(ServiceName);
        mockRepository = module.get(getRepositoryToken(User));
        mockConnection = module.get<Connection>(Connection);
    });
        it('should create a new user and return it using Repository', async () => {
            // some test that passes using mockRepository
        });

        it('should create a new user and return it using QueryBuilder (with mocked Connection)', async () => {
            expect(await service.createUserQueryBuilder(user)).toEqual(user);
            expect(mockConnection.createQueryBuilder).toBeCalled();
            expect(mockConnection.createQueryBuilder()['insert']).toBeCalled();
            expect(mockConnection.createQueryBuilder()['into']).toBeCalled();
            expect(mockConnection.createQueryBuilder()['values']).toBeCalled();
            expect(mockConnection.createQueryBuilder()['execute']).toBeCalled();
        })

這是第二個測試, it('should create a new user and return it using QueryBuilder (with mocked Connection)' ,觸發以下錯誤:

  ● service tests › Service Functions › should create a new user and return it using QueryBuilder (with mocked Connection)

    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.getConnection (index.ts:252:35)
      at ServiceName.createUserQueryBuilder (somefile:19:11)
      at Object.it (somefile:134:34)

最簡單的解決方案是更改您的createUserQueryBuilder方法,如下所示:

async createUserQueryBuilder(user: User): Promise<User> {
  await this.usersRepository
    .createQueryBuilder()
    .insert()
    .into(User)
    .values([
        user, 
     ])
    .execute();
  return user;  
}

然后您可以更新存儲庫模擬repositoryMockFactory

const repositoryMockFactory: () => MockType<Repository<any>> = jest.fn(() => ({ 
  create: jest.fn(),
  save: jest.fn(),
  createQueryBuilder: jest.fn().mockReturnThis(),
  getMany: jest.fn().mockReturnValue(allUsers),
  insert: jest.fn().mockReturnThis(),
  into: jest.fn().mockReturnThis(),
  values: jest.fn().mockReturnThis(),
  execute: jest.fn().mockReturnValue(user),
}));

更新:

根據您的要求,您也可以這樣做。

更新您的spec.ts文件,

import * as typeorm from 'typeorm';

const getConnectionSpy = jest.spyOn(typeorm, 'getConnection');
getConnectionSpy.mockImplementation(() => ({
  createQueryBuilder: jest.fn().mockReturnThis(),
  getMany: jest.fn().mockReturnValue(allUsers),
  insert: jest.fn().mockReturnThis(),
  into: jest.fn().mockReturnThis(),
  values: jest.fn().mockReturnThis(),
  execute: jest.fn().mockReturnValue(user),
}));

請注意,您必須相應地更新您的其他typeorm導入。 例如: typeorm.Connection

這只是為了讓您了解如何做到這一點。 由於我沒有對此進行測試,因此可能存在語法錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM