6
votes

I'm new at typescript. My Nestjs project app is something like this. I'm trying to use repository pattern, so i separated business logic (service) and persistance logic (repository)

UserRepository

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { UserEntity } from './entities/user.entity';

@Injectable()
export class UserRepo {
  constructor(@InjectRepository(UserEntity) private readonly repo: Repository<UserEntity>) {}

  public find(): Promise<UserEntity[]> {
    return this.repo.find();
  }
}

UserService

import { Injectable } from '@nestjs/common';
import { UserRepo } from './user.repository';

@Injectable()
export class UserService {
  constructor(private readonly userRepo: UserRepo) {}

  public async get() {
   return this.userRepo.find();
  }
}

UserController

import { Controller, Get } from '@nestjs/common';

import { UserService } from './user.service';

@Controller('/users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  // others method //

  @Get()
  public async getUsers() {
    try {
      const payload = this.userService.get();
      return this.Ok(payload);
    } catch (err) {
      return this.InternalServerError(err);
    }
  }
}

How do i create unit testing for repository, service & controller without actually persist or retrieve data to DB (using mock)?

1

1 Answers

9
votes

Mocking in NestJS is pretty easily obtainable using the testing tools Nest exposes is @nestjs/testing. In short, you'll want to create a Custom Provider for the dependency you are looking to mock, and that's all there is. However, it's always better to see an example, so here is a possibility of a mock for the controller:

describe('UserController', () => {
  let controller: UserController;
  let service: UserService;
  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      controllers: [UserController],
      providers: [
        {
          provide: UserService,
          useValue: {
            get: jest.fn(() => mockUserEntity) // really it can be anything, but the closer to your actual logic the better
          }
        }
      ]
    }).compile();
    controller = moduleRef.get(UserController);
    service = moduleRef.get(UserService);
  });
});

And from there you can go on and write your tests. This is pretty much the same set up for all tests using Nest's DI system, the only thing to be aware of is things like @InjectRepository() and @InjectModel() (Mongoose and Sequilize decorators) where you'll need to use getRepositoryToken() or getModelToken() for the injection token. If you're looking for more exmaples take a look at this repository