'How can I mock nest typeorm database module in end to end (e2e) tests?

all. Include details about your goal: I'm trying to mock repository in e2e test

Describe expected and actual results: Request to server will not have access to persistent layer. We should mock connection and repository.

I've updated code but the repository still not overrided. Maybe I need to implement it through a Facade provider

You can play with code here My code



Solution 1:[1]

You could use TypeORM fixtures, they allow you to create fixtures / fake data for use while developing or testing your code.

npm install typeorm-fixtures-cli --save-dev

Fixtures can be expressed in YAML files. For example:

entity: User
items:
  user{1..10}:
    username: bob
    fullname: Bob
    birthDate: 1980-10-10
    email: [email protected]
    favoriteNumber: 42

The library integrates Faker to help generate fake data such as names, e-mail addresses, phone numbers...etc. You can also establish relations between different fixtures.

Afterwards you can load the fixtures and use them with TypeORM.

const loadFixtures = async (fixturesPath: string) => {
  let connection;

  try {
    connection = await createConnection();
    await connection.synchronize(true);

    const loader = new Loader();
    loader.load(path.resolve(fixturesPath));

    const resolver = new Resolver();
    const fixtures = resolver.resolve(loader.fixtureConfigs);
    const builder = new Builder(connection, new Parser());

    for (const fixture of fixturesIterator(fixtures)) {
      const entity = await builder.build(fixture);
      await getRepository(entity.constructor.name).save(entity);
    }
  } catch (err) {
    throw err;
  } finally {
    if (connection) {
      await connection.close();
    }
  }
};

You can combine this with an in-memory SQLLite database. Just have TypeORM generate the database based on the entity metadata. Use fixtures to load up the fake data into the in-memory database and then run your tests.

Solution 2:[2]

Use it in app.module.ts TypeOrmModule.forRoot() and TypeOrmModule.forFeature([CatEntity]) in cats.module.ts

 import { getRepositoryToken } from '@nestjs/typeorm';


 beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
            // import modules, the modules should import the entities they deal with.
            // The testing module should be barebones
            imports: [
                // basically looks like a unit test but goes through the HTTP motions
                // if you want to include the AppModule you'll need to create a configuration
                // for the database module (TypeORM) that will be accessible in a testing context
                // AppModule,
                CatModule,
            ],
        })
            // this is for overriding a provider that exists in a module already (such as the ProjectsModule)
            .overrideProvider(getRepositoryToken(ProjectEntity))
            // this is how you give the factory, value, or class to use instead
            .useFactory({
                factory: () => ({
                    create: jest.fn(() => new Promise((resolve) => resolve(cat))),
                    find: jest.fn(() => new Promise((resolve) => resolve([cat]))),
                    update: jest.fn((id, project2) => new Promise((resolve) => resolve(cat2))),
                    findOne: jest.fn(
                        ({ uuid }) =>
                            new Promise((resolve) => {
                                resolve(cat);
                            }),
                    ),
                    delete: jest.fn((uuid) => new Promise((resolve) => resolve())),
                    save: jest.fn(
                        (data) =>
                            new Promise((resolve) => {
                                // data = data.uuid === undefined ? data.uuid = uuid() : data;
                                resolve(data);
                            }),
                    ),
                }),
            })
            .compile();
        app = module.createNestApplication();

        await app.init();
    });

I am available to answer to any question

Solution 3:[3]

I found the typeorm-test-transactions library that saved my day.

It will not mock the database, instead it will rollback all the transactions made inside its runInTransaction function. this is an example

// import the library functions
import {
  runInTransaction,
  initialiseTestTransactions,
} from 'typeorm-test-transactions';

// ...

initialiseTestTransactions();

describe('Test endpoint', () => {
  let app: INestApplication;

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('Endpoint shuld work /endpoint', async () => {

    // the database operations inside runInTransaction will be rolled back
    await runInTransaction(async () => {
      const email = '[email protected]'
      const password = '12345678'

      const userrepo = getRepository(User)
      const user = userrepo.create({email, password, privilege})
      return await userrepo.save(user)

      await request(app.getHttpServer())
        .get('/endpoint')
        .expect(200);
    })()
  });
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Christophe Geers
Solution 2 gian848396
Solution 3