How should I test a controller, which has auth service and user service ? I am trying to follow TDD methodologies, from book, but it doesn't work like that anymore.
Any solutions?
This is a controller I want to test: auth.controller.ts
import { Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UserService } from '../user/user.service';
@Controller('auth')
export class AuthController {
constructor(
private readonly authService: AuthService,
private readonly userService: UserService,
) {}
@Post()
async signup() {
throw new Error('Not Implemented!');
}
@Post()
async signin() {
throw new Error('Not Implemented Error!');
}
}
This is a service that will be used by auth controller to handle actions:auth.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class AuthService {}
This is external service that I will need to use in order to find and authenticate useruser.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class UserService {}
Here I am trying to do some TDD tests for auth controller:auth.controller.spec.ts
import { Test } from '@nestjs/testing';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UserService } from '../user/user.service';
describe('EntriesController', () => {
let authController: AuthController;
let authSrv: AuthService;
beforeEach(async () => {
const module = await Test.createTestingModule({
controllers: [AuthController],
providers: [AuthService, UserService],
})
.overrideProvider(AuthService)
.useValue({ signup: () => null, signin: () => null })
.compile();
authController = await module.get<AuthController>(AuthController);
authSrv = await module.get<AuthService>(AuthService);
});
describe('signup', () => {
it('should add new user to the database', async () => {
expect(await authController.signin()).toBe(true);
console.log(authController);
});
});
describe('signin', () => {
it('should sign in user, if credentials valid', async () => {});
});
});
Instead of using overrideProvider
you should be setting the mock directly in the providers array with something similar to this:
beforeEach(async () => {
const module = await Test.createTestingModule({
controllers: [AuthController],
providers: [
{
provide: AuthService,
useValue: { signup: () => null, signin: () => null }
},
UserService
],
})
.compile();
authController = await module.get<AuthController>(AuthController);
authSrv = await module.get<AuthService>(AuthService);
});
The same should be done for UserService
, this way you are creating true unit tests, only testing the immediate class and ignoring the rest. This repository of mine shows a lot of different testing examples for projects using NestJS. May be helpful to take a look.