使用 NestJS 服务单元测试未找到连接“默认”
Posted
技术标签:
【中文标题】使用 NestJS 服务单元测试未找到连接“默认”【英文标题】:Connection "default" was not found with NestJS Unit Testing of Service 【发布时间】:2021-08-03 21:28:18 【问题描述】:我目前正在对我的 NestJS 服务进行单元测试。我的实体称为“用户”,我建立了一个基本服务,允许我与 MS SQL 服务器交互,并在我的控制器中建立 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)
【问题讨论】:
【参考方案1】:最简单的解决方案是更改您的 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
这只是为了让您了解如何操作。由于我没有对此进行测试,因此可能存在语法错误。
【讨论】:
感谢您的回答!确实,这似乎有效;但我真的很想坚持使用getConnection()
。 (真的,这是为了练习;我的新角色涉及 NestJS)。您对模拟 getConnection 有什么建议吗?我找到了一种在我的服务中使用@InjectConnection() private connection: Connection
并将其与我的spec.ts 文件中的provide: Connection, useFactory: mockConnectionFactory,
结合起来的方法(并且它可以工作),但在这里我模拟的是注入连接,而不是导入的getConnection .如果我可以模拟导入的 getConnection,那就太好了。
我更新了我的答案,但我不能保证它会起作用。祝你的新角色好运! ?
嗯,还是不行;但感谢您的回答!我觉得我需要在这里和那里做一些调整,也许......
编辑:我将您的方法调整为一个更简单的示例,其中我使用 getManager()
后跟 delete
单个函数并且它有效!我很确定需要进行一些进一步的调整才能使createQueryBuilder
中的函数链正常工作(它可能要复杂得多......)。再次感谢!
哇,太好了。很高兴我能帮忙?以上是关于使用 NestJS 服务单元测试未找到连接“默认”的主要内容,如果未能解决你的问题,请参考以下文章
未找到连接“默认”-TypeORM、NestJS 和外部 NPM 包