Webeleon / unit-testing-nestjs-using-typeorm-in-memory

a dev.to article on unit testing nestjs project using typeorm and in memory db
5 stars 1 forks source link

banner

Unit testing NestJS with Typeorm in memory

Assuming you already configured TypeORM in your NestJS project. If you need to setup TypeORM, consider reading the awesome NestJS documentation.

For the sake of testing something, I'll setup a simple API that will serve spaceships! You can access the sample repository on github.

Install SQLITE

npm i -D better-sqlite3

A few helpers

Ok, we can write this for every test files BUT we are lazy developers and will not spend our time re-writing the same code over and over and over...

Let's write a simple helper function that will provide an easy to import pre-configured TypeORM module! src/test-utils/TypeORMSQLITETestingModule.ts

import { TypeOrmModule } from '@nestjs/typeorm';
import { Spaceship } from '../spaceships/spaceship.entity';

export const TypeOrmSQLITETestingModule = () => [
  TypeOrmModule.forRoot({
    type: 'better-sqlite3',
    database: ':memory:',
    dropSchema: true,
    entities: [Spaceship],
    synchronize: true,
  }),
  TypeOrmModule.forFeature([Spaceship]),
];

This one is not mandatory but a simple test dataset is always a nice to have. src/test-utils/testDataset.seed.ts

import { getConnection } from 'typeorm';
import { Spaceship } from '../spaceships/spaceship.entity';

export const testDatasetSeed = async () => {
  const connection = await getConnection();
  const entityManager = connection.createEntityManager();

  entityManager.insert<Spaceship>(Spaceship, {
    name: 'moa',
    type: 'cruiser',
    origin: 'caldari',
  });
  entityManager.insert<Spaceship>(Spaceship, {
    name: 'caracal',
    type: 'cruiser',
    origin: 'caldari',
  });
  entityManager.insert<Spaceship>(Spaceship, {
    name: 'rokh',
    type: 'battleship',
    origin: 'caldari',
  });
};

Using the helpers in a test file

In order to allow tests to use the im memory database, you'll just need to call the function ...TypeOrmSQLITETestingModule() and spread it since it provide the TypeOrmModule.forRoot and TypeOrmModule.forFeature.

Finally, seed the test data (or not) await testDatasetSeed();.

import { Test, TestingModule } from '@nestjs/testing';
import { SpaceshipsService } from './spaceships.service';
import { TypeOrmSQLITETestingModule } from '../test-utils/TypeOrmSQLITETestingModule';
import { testDatasetSeed } from '../test-utils/testDataset.seed';

describe('SpaceshipsService', () => {
  let service: SpaceshipsService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [...TypeOrmSQLITETestingModule()],
      providers: [SpaceshipsService],
    }).compile();

    service = module.get<SpaceshipsService>(SpaceshipsService);
    await testDatasetSeed();
  });

  it('listSpaceships', async () => {
    const spaceships = await service.listSpaceships();
    expect(spaceships).toHaveLength(3);
  });
});

Questions?

https://media.giphy.com/media/Ss0aKjyh6UgHhnv0yG/giphy.gif

I'll be glad to answers questions in the comments.

If you liked my discord consider joining my coding lair! :phone:Webeleon coding lair on discord

You can also email me and offer me a contract :moneybag: :envelope:Email me!

And since I'm a nice guy, here, take this sample repo containing a working codebase! :gift:Get the code of the tuto from github