MikroORM jest unit test - how to provide entity repository with connect: false

442 views Asked by At

When I use MikroORM.init() in unit test I want to use connect:false option to not create db connection, but test the entity behaviour for example more complex update method like: "wrap(existingCook).assign(updateCookDto);"

important I don't want to mock functions from entity repository or connect to real db.

My setup: Nestjs + MikroORM version: 5.5.3

cook.entity.ts

import { Entity, PrimaryKey } from '@mikro-orm/core';

import { v4 as uuid } from 'uuid';

import { Cook } from '../../../domain';

@Entity({ tableName: 'cook' })
export class CookEntity implements Cook {
@PrimaryKey()
id: string = uuid();
}

cook.service.ts

import { Injectable } from '@nestjs/common';

import { EntityRepository } from '@mikro-orm/core';
import { InjectRepository } from '@mikro-orm/nestjs';

import { Cook } from '../../domain';

import { CookEntity } from './entities';

@Injectable()
export class CookService {
constructor(@InjectRepository(CookEntity) private readonly \_cookRepository: EntityRepository\<CookEntity\>) {}

    async findAll(): Promise<Array<Cook>> {
        return this._cookRepository.findAll();
    }

}

cook.service.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { CookService } from './cook.service';
import { getRepositoryToken } from '@mikro-orm/nestjs';
import { CookEntity } from './entities';
import { EntityRepository, MikroORM } from '@mikro-orm/core';
import { defineConfig } from '@mikro-orm/postgresql';

const config = defineConfig({
  connect: false,
  type: 'postgresql',
  dbName: 'cook',
  schema: 'cook',
  debug: true,
  entities: [CookEntity],
});

describe('CookService', () =\> {
let orm: MikroORM;
let cookRepository: EntityRepository\<CookEntity\>;

    let service: CookService;
    let testingModule: TestingModule;
    
    beforeEach(async () => {
        orm = await MikroORM.init(config);
        cookRepository = orm.em.getRepository(CookEntity);
    
        testingModule = await Test.createTestingModule({
            providers: [
                CookService,
                {
                    provide: getRepositoryToken(CookEntity),
                    useValue: cookRepository,
                },
            ],
        }).compile();
    
        service = testingModule.get<CookService>(CookService);
    });
    
    it('should be defined', async () => {
        // Then
        expect(service).toBeDefined();
    
        await service.findAll();
    });

});

Error: enter image description here

1

There are 1 answers

8
Martin Adámek On

You should let the nest DI create the ORM instance, you should alter the config the nest DI uses, that way the context should be set up correctly.

The way you do it now literally uses the global ORM instance, so the validation error is correct. On the other hand, if you won't be reusing this ORM instance across multiple tests, it should be fine to just disable the validation, either with the allowGlobalContext option, or simply by forking the EM:

orm = await MikroORM.init(config);
cookRepository = orm.em.fork().getRepository(CookEntity); // <-- fork first
    
testingModule = await Test.createTestingModule({
    providers: [
        CookService,
        {
            provide: getRepositoryToken(CookEntity),
            useValue: cookRepository,
        },
    ],
}).compile();

Note that the explicit forking this way will work, but only if you don't use other repositories or the EM directly, so the allowGlobalContext is preferrable here.