Я хотел бы иметь возможность протестировать мой сервис Nest с реальной базой данных. Я понимаю, что большинство модульных тестов должны использовать фиктивный объект, но иногда имеет смысл проводить тестирование и против самой базы данных.

Я искал в «Гнездо» вопросы SO и GH и начинаю переходить к завершению всех ответов. :-)

Я пытаюсь работать с https://github.com/nestjs/nest/issues/363#issuecomment-360105413 . Ниже приведен мой модульный тест, в котором для передачи хранилища моему классу обслуживания используется пользовательский поставщик.

describe("DepartmentService", () ={amp}gt; { const token = getRepositoryToken(Department); let service: DepartmentService; let repo: Repository{amp}lt;Department{amp}gt;; beforeEach(async () ={amp}gt; { const module: TestingModule = await Test.createTestingModule({ providers: [ DepartmentService, { provide: token, useClass: Repository } ] }).compile(); service = module.get{amp}lt;DepartmentService{amp}gt;(DepartmentService); repo = module.get(token); }); 

Все компилируется правильно, TypeScript кажется счастливым. Однако, когда я пытаюсь выполнить create или save в моем экземпляре Repository , базовый Repository кажется неопределенным. Вот обратная трассировка стека:

 TypeError: Cannot read property 'create' of undefined at Repository.Object.{amp}lt;anonymous{amp}gt;.Repository.create (repository/Repository.ts:99:29) at DepartmentService.{amp}lt;anonymous{amp}gt; (relational/department/department.service.ts:46:53) at relational/department/department.service.ts:19:71 at Object.{amp}lt;anonymous{amp}gt;.__awaiter (relational/department/department.service.ts:15:12) at DepartmentService.addDepartment (relational/department/department.service.ts:56:16) at Object.{amp}lt;anonymous{amp}gt; (relational/department/test/department.service.spec.ts:46:35) at relational/department/test/department.service.spec.ts:7:71 

Похоже, что экземпляр EntityManager с классом Repository TypeORM не инициализируется; это undefined ссылка, на которую жалуется эта обратная трассировка.

Как получить, чтобы Repository и EntityManager правильно инициализировались?

спасибо, Том

Чтобы правильно инициализировать typeorm, вы должны просто иметь возможность импортировать TypeOrmModule в свой тест:

 Test.createTestingModule({ imports: [ TypeOrmModule.forRoot({ type: 'mysql', // ... }), TypeOrmModule.forFeature([Department]) ] 

Вот обновление к тесту, в котором используется предложение Ким Керн.

 describe("DepartmentService", () ={amp}gt; { let service: DepartmentService; let repo: Repository{amp}lt;Department{amp}gt;; let module: TestingModule; beforeAll(async () ={amp}gt; { module = await Test.createTestingModule({ imports: [ TypeOrmModule.forRoot(), TypeOrmModule.forFeature([Department]) ], providers: [DepartmentService] }).compile(); service = module.get{amp}lt;DepartmentService{amp}gt;(DepartmentService); repo = module.get{amp}lt;Repository{amp}lt;Department{amp}gt;{amp}gt;(getRepositoryToken(Department)); }); afterAll(async () ={amp}gt; { module.close(); }); it("should be defined", () ={amp}gt; { expect(service).toBeDefined(); }); // ... } 

Я предпочитаю не использовать @nestjs/testing для простоты.

Прежде всего, создайте многоразового помощника:

 /* src/utils/testing-helpers/createMemDB.js */ import { createConnection, EntitySchema } from 'typeorm' type Entity = Function | string | EntitySchema{amp}lt;any{amp}gt; export async function createMemDB(entities: Entity[]) { return createConnection({ // name, // let TypeORM manage the connections type: 'sqlite', database: ':memory:', entities, dropSchema: true, synchronize: true, logging: false }) } 

Затем напишите тест:

 /* src/user/user.service.spec.ts */ import { Connection, Repository } from 'typeorm' import { createMemDB } from '../utils/testing-helpers/createMemDB' import UserService from './user.service' import User from './user.entity' describe('User Service', () ={amp}gt; { let db: Connection let userService: UserService let userRepository: Repository{amp}lt;User{amp}gt; beforeAll(async () ={amp}gt; { db = await createMemDB([User]) userRepository = await db.getRepository(User) userService = new UserService(userRepository) // {amp}lt;--- manually inject }) afterAll(() ={amp}gt; db.close()) it('should create a new user', async () ={amp}gt; { const username = 'HelloWorld' const password = 'password' const newUser = await userService.createUser({ username, password }) expect(newUser.id).toBeDefined() const newUserInDB = await userRepository.findOne(newUser.id) expect(newUserInDB.username).toBe(username) }) }) 

См. Https://github.com/typeorm/typeorm/issues/1267#issuecomment-483775861.