Get Mongoose instance in NestJS e2e testing

Viewed 998

I'm starting to write e2e tests for my NestJS API, and I would like to use a test database. I imported the MongooseModule in the test module, and it's correctly using the expected test database.

Then, I'd like to clear the collection and re-insert fixtures before my tests. In order to do that, I'd like to use the Mongoose instance used by NestJS. But I didn't succeed, and finally created a second connection (in the beforeAll hook)

I didn't find any solutions yet to avoid this.

Here is the code :


describe('Color', () => {
  let app: INestApplication
  let db: Connection

  beforeAll(async () => {
    db = await mongoose.createConnection(process.env.MONGO_TEST_URL, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useCreateIndex: true
    })

    db.model('Color', ColorSchema)
  })

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [
        MongooseModule.forRoot(process.env.MONGO_TEST_URL, {
          useCreateIndex: true,
          useFindAndModify: false
        }),
        AppModule
      ]
    }).compile()

    await db.model('Color').deleteMany({})
    await db.model('Color').insertMany(ColorFixtures)

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

  afterAll(async () => {
    await db.close()
    await app.close()
  })

  it('/ (GET)', () => {
    return request(app.getHttpServer())
      .post('/graphql')
      .send({
        operationName: 'findAll',
        query: 'query findAll { colors { id name } }',
        variables: {}
      })
      .expect(200)
      .expect({})
  })
})

Any idea?

1 Answers

I write my own e2e tests for authentication (/signup) sample:

afterEach is a good place for removing data from colletion.

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from './../src/app.module';
import { Connection } from 'mongoose';
import { getConnectionToken } from '@nestjs/mongoose';
import { SignupUserDto } from '../src/authentication/dto/signup-user.dto';
import { UsersService } from '../src/users/users.service';

describe('Authentication (e2e)', () => {
  let app: INestApplication;
  let connection: Connection;
  let usersService: UsersService;
  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    usersService = moduleFixture.get<UsersService>(UsersService);
    //connection = await moduleFixture.get(getConnectionToken());
    app = moduleFixture.createNestApplication();
    await app.init();
  });
  afterAll(async () => {
    // await connection.close(/*force:*/ true); // <-- important
    await app.close();
  });

  afterEach(async () => {
    // truncate data from DB...
    await usersService.removeAll();
  });
  describe('POST /signup', () => {
    const signupData: SignupUserDto = {
      email: 'testd@test.com',
      name: 'testuser',
      password: 'test123456',
    };

    it('should return 400 error if all inputs not provided', () => {
      let data = { ...signupData };
      delete data['password'];
      return request(app.getHttpServer())
        .post('/auth/signup')
        .send(data)
        .expect(400);
    });

    it('should return 400  if email is in use', async () => {
      await usersService.create(signupData);
      return request(app.getHttpServer())
        .post('/auth/signup')
        .send(signupData)
        .expect(400);
    });
  });
});

and db connetion is set in app.module.ts:

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      cache: true,
    }),
    MongooseModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        uri:
          config.get('NODE_ENV') === 'test'
            ? config.get<string>('MONGO_TEST_CONNECTION')
            : config.get<string>('MONGO_CONNECTION'),
        autoIndex: false,
      }),
    }),
    // add throttle based on api (REST,Graphql,Socket,...)
    UsersModule,
    AuthenticationModule,
  ]
  ,...
  });
Related