Unit Testing in NestJS - CouponService
Step 1: Boilerplate Setup
import { Test, TestingModule } from '@nestjs/testing';
import { CouponService } from './[Link]';
import { CouponRepository } from '../repositories/[Link]';
import { ClientExternalService } from '@modules/client/client/services/[Link]';
describe('CouponService', () => {
let service: CouponService;
beforeEach(async () => {
const module: TestingModule = await [Link]({
providers: [
CouponService,
{ provide: CouponRepository, useValue: {} },
{ provide: ClientExternalService, useValue: {} },
],
}).compile();
service = [Link]<CouponService>(CouponService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
Step 2: Mock Dependencies
const mockCouponRepository = {
getRepository: [Link]().mockReturnValue({
save: [Link](),
findOne: [Link](),
delete: [Link](),
create: [Link](),
}),
findUnmappedGlobalCouponsForOutlet: [Link](),
};
const mockClientExternalService = {
// mock any external calls if needed
};
Step 3: Use Mocks in Testing Module
beforeEach(async () => {
const module: TestingModule = await [Link]({
providers: [
CouponService,
{ provide: CouponRepository, useValue: mockCouponRepository },
{ provide: ClientExternalService, useValue: mockClientExternalService },
],
}).compile();
service = [Link]<CouponService>(CouponService);
});
Step 4: Full Test File
import { Test, TestingModule } from '@nestjs/testing';
import { CouponService } from './[Link]';
import { CouponRepository } from '../repositories/[Link]';
import { ClientExternalService } from '@modules/client/client/services/[Link]';
import { getRepository } from 'typeorm';
import { CouponEntity } from '../entities/[Link]';
import { NotFoundException } from '@nestjs/common';
import { UserTypeEnum } from '@src/utils/enums/[Link]';
import { DiscountTypeEnum } from '../enums/[Link]';
import { CouponTypeEnum } from '../enums/[Link]';
describe('CouponService', () => {
let service: CouponService;
let mockClientExternalService = {}
let findOneMock: [Link];
let mockRepositoryInstance: any;
let mockCouponRepository: any;
beforeEach(async () => {
findOneMock = [Link]();
mockRepositoryInstance = {
save: [Link](),
findOne: findOneMock,
find: [Link](),
delete: [Link](),
create: [Link](),
};
mockCouponRepository = {
getRepository: [Link](() => mockRepositoryInstance),
findUnmappedGlobalCouponsForOutlet: [Link](),
};
const module: TestingModule = await [Link]({
providers: [
CouponService,
{ provide: CouponRepository, useValue: mockCouponRepository },
{ provide: ClientExternalService, useValue: mockClientExternalService },
],
}).compile()
service = [Link]<CouponService>(CouponService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('getCouponByIdOrThrow', () => {
it('should return a coupon if found', async () => {
const coupon = { id: 1 } as CouponEntity;
[Link](coupon);
const result = await [Link](1);
expect(result).toEqual(coupon);
});
it('should throw NotFoundException if coupon not found', async () => {
[Link](null);
await expect([Link](1)).[Link](NotFoundException);
});
});
describe('create', () => {
it('should create and return a coupon', async () => {
const dto = {
code: 'NEW123',
discountType: [Link],
discountValue: 100,
validFrom: new Date(),
validTo: new Date([Link]() + 86400000),
couponType: CouponTypeEnum.ONE_TIME,
isActive: true,
};
const created = { ...dto, owner: [Link] } as CouponEntity;
[Link](created);
[Link](created);
const result = await [Link]({ ...dto, owner: [Link] });
expect(result).toEqual(created);
});
describe('isCouponCodeUnique', () => {
it('should return false if coupon code exists', async () => {
const code = 'EXIST123';
[Link]().[Link]({ code });
const result = await [Link](code);
expect([Link]).toBe(false);
});
it('should return true if coupon code is unique', async () => {
const code = 'UNIQUE123';
[Link]().[Link](null);
const result = await [Link](code);
expect([Link]).toBe(true);
});
});
describe('delete', () => {
it('should call delete after finding the coupon', async () => {
const id = 1;
[Link]().[Link]({ id });
[Link]().[Link]({});
await [Link](id);
expect([Link]().delete).toHaveBeenCalledWith({ id });
});
});
});
});