unit test in Nodejs using Jest - node.js

I have a method in controller, as below:
import { calcu } from '../services/myServices';
export const getProduct = (req, res, next) => {
try {
const { type } = req.params;
const { id, productCode } = req.body;
if (!id || !productCode) {
res.status(400).json({ error: { message: 'Id or productCode is required' } });
} else {
switch (type.toUpperCase()) {
case 'X':
try {
const result = calcu(id, productCode);
res.status(200).json(result);
} catch (err) {
res.status(400).json({ error: { message: err.message } });
}
break;
default:
res.status(400).json({ error: { message: `type ${type} is not support` } });
}
}
} catch (err) {
next(err);
}
};
This my unit test code in this case:
import { getProduct } from './quotationController';
describe('Controller', () => {
let json, res, status;
test('Should return message error if the id or productCode is missing', () => {
const req = {
body: { id: "1111" },
param: { type: "qqqqq" }
};
const next = err => err.message;
const result = getProduct(req, res, next);
//expect(result).toBe(undefined);
expect(result).toEqual({
code: 400,
message: 'Id or productCode is required'
});
});
})
I got an error when I ran the unit test code:
result is undefined.

Here is the unit test solution:
controller.js:
import { calcu } from './service';
export const getProduct = (req, res, next) => {
try {
const { type } = req.params;
const { id, productCode } = req.body;
if (!id || !productCode) {
res.status(400).json({ error: { message: 'Id or productCode is required' } });
} else {
switch (type.toUpperCase()) {
case 'X':
try {
const result = calcu(id, productCode);
res.status(200).json(result);
} catch (err) {
res.status(400).json({ error: { message: err.message } });
}
break;
default:
res.status(400).json({ error: { message: `type ${type} is not support` } });
}
}
} catch (err) {
next(err);
}
};
service.js: (simulated)
export function calcu(id, code) {
return id + code;
}
controller.test.js:
import { getProduct } from './controller';
import { calcu } from './service';
jest.mock('./service.js', () => ({ calcu: jest.fn() }));
describe('Controller', () => {
let mRes;
let mNext;
beforeEach(() => {
mRes = { status: jest.fn().mockReturnThis(), json: jest.fn() };
mNext = jest.fn();
});
afterEach(() => {
jest.resetAllMocks();
});
test('Should return message error if the id or productCode is missing', () => {
const mReq = { body: { id: '1111' }, params: { type: 'qqqqq' } };
getProduct(mReq, mRes, mNext);
expect(mRes.status).toBeCalledWith(400);
expect(mRes.status().json).toBeCalledWith({ error: { message: 'Id or productCode is required' } });
});
test('should call next when error happens', () => {
const mReq = {};
getProduct(mReq, mRes, mNext);
expect(mNext).toBeCalledWith(expect.any(Error));
});
test('should return message error if type is not support', () => {
const mReq = { params: { type: 'qqqqq' }, body: { id: '1111', productCode: '22' } };
getProduct(mReq, mRes, mNext);
expect(mRes.status).toBeCalledWith(400);
expect(mRes.status().json).toBeCalledWith({ error: { message: `type ${mReq.params.type} is not support` } });
});
test('should return message error if calcu errors', () => {
const mReq = { params: { type: 'x' }, body: { id: '1111', productCode: '22' } };
const mError = new Error('calc error');
calcu.mockImplementationOnce(() => {
throw mError;
});
getProduct(mReq, mRes, mNext);
expect(calcu).toBeCalledWith('1111', '22');
expect(mRes.status).toBeCalledWith(400);
expect(mRes.status().json).toBeCalledWith({ error: { message: mError.message } });
});
test('should return correct calc result', () => {
const mReq = { params: { type: 'x' }, body: { id: '1111', productCode: '22' } };
calcu.mockReturnValueOnce({ data: 'fake data' });
getProduct(mReq, mRes, mNext);
expect(calcu).toBeCalledWith('1111', '22');
expect(mRes.status).toBeCalledWith(200);
expect(mRes.status().json).toBeCalledWith({ data: 'fake data' });
});
});
Unit test result with 100% coverage:
PASS src/stackoverflow/59508494/controller.test.js (7.379s)
Controller
✓ Should return message error if the id or productCode is missing (6ms)
✓ should call next when error happens (1ms)
✓ should return message error if type is not support (1ms)
✓ should return message error if calcu errors (2ms)
✓ should return correct calc result (2ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
controller.js | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 8.731s, estimated 10s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59508494

Related

"Missing region in config" after attempting to mock SecretsManager with Jest

I'm currently attempting to mock AWS SecretsManager for my unit testing with Jest, and everytime I'm hit with the ConfigError
My code is somewhat like this
//index.ts
import SM from "aws-sdk/clients/secretsmanager"
const secretManagerClient = new SM()
...
export const randomMethod = async (a: string, b: string) => {
let secret
const personalToken = {
SecretId: process.env.secretId,
}
secretManagerClient
.getSecretValue(personalToken, (err, data) => {
if (err) {
console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`)
} else if (data && data.SecretString) {
secret = data.SecretString
}
})
}
My mock goes like this :
//index.test.js
const mockGetSecretValue = jest.fn((SecretId) => {
switch (SecretId) {
case process.env.GITHUB_PERSONAL_TOKEN:
return {
SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
}
default:
throw Error("secret not found")
}
})
jest.mock("aws-sdk/clients/secretsmanager", () => {
return jest.fn(() => {
return {
getSecretValue: jest.fn(({ SecretId }) => {
return mockGetSecretValue(SecretId)
}),
promise: jest.fn(),
}
})
})
However, I get this error thrown at me : ConfigError: Missing region in config, which I understand to some extent, however I don't understand why it occurs here in the mocking part...
Thanks in advance!
EDIT: Thanks to the 1st answer, I've managed to stop having this error. However, the getSecretValue() method is not returning the Secret value I want.
You should NOT use the callback of .getSecretValue() method with .promise() together. Just choose one of them. The error means you didn't mock the secretsmanager class correctly of aws-sdk.
E.g.
index.ts:
import SM from 'aws-sdk/clients/secretsmanager';
const secretManagerClient = new SM();
export const randomMethod = async () => {
const personalToken = {
SecretId: process.env.secretId || '',
};
try {
const data = await secretManagerClient.getSecretValue(personalToken).promise();
return data.SecretString;
} catch (err) {
console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`);
}
};
index.test.ts:
import { randomMethod } from '.';
import SM from 'aws-sdk/clients/secretsmanager';
import { mocked } from 'ts-jest/utils';
import { PromiseResult } from 'aws-sdk/lib/request';
jest.mock('aws-sdk/clients/secretsmanager', () => {
const mSecretManagerClient = {
getSecretValue: jest.fn().mockReturnThis(),
promise: jest.fn(),
};
return jest.fn(() => mSecretManagerClient);
});
describe('69977310', () => {
test('should get secret value', async () => {
process.env.secretId = 's1';
const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());
mGetSecretValueRequest.promise.mockResolvedValue({
SecretString: JSON.stringify({ password: '123456' }),
} as PromiseResult<any, any>);
const actual = await randomMethod();
expect(actual).toEqual(JSON.stringify({ password: '123456' }));
expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
});
test('should throw error', async () => {
process.env.secretId = 's1';
const logSpy = jest.spyOn(console, 'error').mockImplementation(() => 'suppress error log for testing');
const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());
const mError = new Error('network');
mGetSecretValueRequest.promise.mockRejectedValue(mError);
await randomMethod();
expect(logSpy).toBeCalledWith(`[SECRETS MANAGER] Error fetching personal token : ${mError}`);
expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
});
});
test result:
PASS examples/69977310/index.test.ts (7.722 s)
69977310
✓ should get secret value (4 ms)
✓ should throw error (1 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 50 | 100 | 100 |
index.ts | 100 | 50 | 100 | 100 | 6
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 8.282 s, estimated 10 s
package versions:
"aws-sdk": "^2.875.0",
"typescript": "^4.1.2",
"jest": "^26.6.3",
I've overlooked the fact that I was using a callback in order to bypass the promise().
The following is the correct code:
const mockGetSecretValue = jest.fn((SecretId, callback) => {
console.log("secretId", SecretId)
switch (SecretId) {
case process.env.GITHUB_PERSONAL_TOKEN:
const data = {
SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
}
callback(null, data)
break;
default:
const err = new Error("secret not found")
throw err
}
})
jest.mock("aws-sdk/clients/secretsmanager", () => {
return jest.fn(() => {
return {
promise: jest.fn(),
getSecretValue: jest.fn(({ SecretId }, callback) => {
return mockGetSecretValue(SecretId, callback)
}),
}
})
})
Thanks again for your help #slideshowp2!

How to call external function in jest

I'm New to unit test and trying to test my controller method.my project architecture design is as follow
Controller->Service->Model.
My test scenarios :
Pass correct parameters to controller method and test success response
Pass Invalid parameters to controller method and test error response
When i going to test scenario 1 ,according to my understanding i want to mock my programService and it return values.I have write test as follow and got errors.
I would really appreciate some one can fix this
ProgramsController.js
const ProgramService = require('../../services/program/programService');
class ProgramsController {
constructor() {
this.programService = new ProgramService();
}
async subscribe(req, res) {
try {
const { userId, uuid, msisdn, body: { programId } } = req;
const data = { userId, programId, msisdn, uuid }
const subscribe = await this.programService.subscribeUser(data);
res.json({
status: true,
message: 'Success',
friendly_message: constant.MSG.SUBSCRIPTION,
data: subscribe
})
} catch (error) {
res.status(500)
.json({
status: false,
message: 'Fail',
friendly_message: constant.MSG.SUBSCRIPTION_FAIL
})
}
}
}
ProgramService.js
class ProgramService {
constructor() {
this.subscriber = new Subscriber();
this.subsciberProgram = new SubsciberProgram()
}
async subscribeUser(data) {
try {
const { msisdn, userId, programId, uuid } = data;
...
return subscribedData;
} catch (error) {
throw error;
}
}
}
module.exports = ProgramService;
test.spec.js
const ProgramsService = require('../src/services/program/programService')
const ProgramsController = require('../src/controllers/programs/programsController')
const programController = new ProgramsController()
const programsService = new ProgramsService()
beforeAll(() => {
db.sequelize.sync({ force: true }).then(() => { });
});
const mockRequest = (userId, uuid, msisdn, body) => ({
userId,
uuid,
msisdn,
body,
});
const mockResponse = () => {
const res = {};
res.status = jest.fn().mockReturnValue(res);
res.json = jest.fn().mockReturnValue(res);
return res;
};
const serviceRecord = { userId: 1, programId: 1, msisdn: '56768382967', uuid: '46651a19-3ef1-4149-818e-9bd8a5f359ef' };
const fakeServiceReturn = { program_id: 1, amount: 5, no_of_questions: 10 }
describe('Subscribe', () => {
test('should return 200', async () => {
const req = mockRequest(
1,
'56768382967',
'46651a19-3ef1-4149-818e-9bd8a5f359ef',
{ 'programId': 1 }
);
const res = mockResponse();
const spy = jest.spyOn(programsService, 'subscribeUser').mockImplementation(() => serviceRecord);
await programController.subscribe(req, res);
expect(programsService.subscribeUser()).toHaveBeenCalledWith(fakeServiceReturn);
expect(res.status).toHaveBeenCalledWith(500);
expect(res.json).toHaveBeenCalledWith({
status: true,
message: 'Success',
friendly_message: 'successfull get data',
data : { program_id: 1, amount: 5, no_of_questions: 10 }
});
spy.mockRestore();
});
});
how can i mock programService.subscribeUser and test success response?
This mock should return a promise:
jest.spyOn(programsService, 'subscribeUser').mockImplementation(() => Promise.resolve(serviceRecord));

Mocking/stubbing a class with Jest in Node.JS

I've got a class that sends a Slack message that looks like this:
class SlackMessage {
constructor(email_address, message) {
this.email_address = email_address;
this.message = message;
this.slackClient = new WebClient(token);
}
async send() {
let user = await this.user();
return await this.slackClient.chat.postMessage({
channel: user.user.id,
text: message,
});
}
async user() {
return await this.slackClient.users.lookupByEmail({
email: email_address
});
}
}
I want to mock the slackClient, so that slackClient.users.lookupByEmail returns a known value, and I can check this.slackClient.chat.postMessage gets called with the expected args, but I can't figure out how to do this. I've tried this (and various other permuations):
jest.mock("#slack/web-api");
describe("SlackMessage", () => {
beforeAll(() => {
WebClient.mockImplementation(() => {
return {
chat: {
postMessage: jest.fn(() => {
return Promise.resolve({})
})
},
users: {
lookupByEmail: jest.fn(() => {
return Promise.resolve({
user: {
id: "1234"
}
})
})
}
};
});
});
test("it sends a slack message", async () => {
message = new SlackMessage("foo#example.com", "Hello there!");
message.send()
expect(message.slackClient.users.lookupByEmail).toHaveBeenCalledWith({
email: "foo#example.com"
})
expect(message.slackClient.chat.postMessage).toHaveBeenCalledWith({
channel: "1234",
text: "Hello there!",
})
})
})
But this gives me the error:
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: {"email": "foo#example.com"}
Number of calls: 0
33 | message.send()
34 |
> 35 | expect(message.slackClient.users.lookupByEmail).toHaveBeenCalledWith({
| ^
36 | email: "foo#example.com"
37 | })
38 | expect(message.slackClient.chat.postMessage).toHaveBeenCalledWith({
at Object.<anonymous> (spec/slack_message.test.js:35:53)
Where am I going wrong?

How to mock a controller?

How to mock this I don't know. Can someone help me on this ?
I want to write the test case for this controller. But I am new to this so where to start and how to write the test case I don't understand.
import { Route } from '../common/ExpressWrapper';
import {partnerDao} from '../factory/AppFactory';
import { keysToLowerCase } from '../util/TpsUtil';
import ErrorResponse from '../models/common/ErrorResponse'
const constants = require('../constants');
const logger = require('../logger/index.ts')('controller/PartnerController');
const GetPartnerByPKController: Route = (req, res) => {
logger.debug("Entering GetPartnerByPKController()");
let uuid = req.params.uuid;
console.time("TimeTaken:DBCall:");
console.log("Entering GetPartnerByPKController()"+uuid);
partnerDao.getPartnerByUuid(uuid).then(result => {
if (result != undefined) {
res.status(200).send(result);
} else {
logger.info("Partner for the uuid:" + uuid + " was not found");
res.status(404).send(new ErrorResponse("Partner not found", "404.1.100", constants.ERROR_LINK + "404.1.100", []));
}
}).catch(error => {
console.log("Error in accessing GetPartnerByPK API", JSON.stringify(error))
logger.error("Error in accessing GetPartnerByPK API", JSON.stringify(error));
res.status(500).send(new ErrorResponse("Internal Server Error", "500.1.103", constants.ERROR_LINK + "500.1.103", [JSON.stringify(error.message)]));
});
console.timeEnd("TimeTaken:DBCall:");
logger.debug("Leaving GetPartnerByPKController()");
}
Here is the unit test solution:
controller.ts:
import { partnerDao } from "./AppFactory";
import ErrorResponse from "./ErrorResponse";
type Route = any;
const constants = {
ERROR_LINK: "ERROR_LINK",
};
export const GetPartnerByPKController: Route = async (req, res) => {
console.debug("Entering GetPartnerByPKController()");
let uuid = req.params.uuid;
console.time("TimeTaken:DBCall:");
console.log("Entering GetPartnerByPKController()" + uuid);
await partnerDao
.getPartnerByUuid(uuid)
.then((result) => {
if (result != undefined) {
res.status(200).send(result);
} else {
console.info("Partner for the uuid:" + uuid + " was not found");
res
.status(404)
.send(new ErrorResponse("Partner not found", "404.1.100", constants.ERROR_LINK + "404.1.100", []));
}
})
.catch((error) => {
console.log("Error in accessing GetPartnerByPK API", JSON.stringify(error));
console.error("Error in accessing GetPartnerByPK API", JSON.stringify(error));
res
.status(500)
.send(
new ErrorResponse("Internal Server Error", "500.1.103", constants.ERROR_LINK + "500.1.103", [
JSON.stringify(error.message),
]),
);
});
console.timeEnd("TimeTaken:DBCall:");
console.debug("Leaving GetPartnerByPKController()");
};
AppFactory.ts:
export const partnerDao = {
async getPartnerByUuid(id) {
return "real data";
},
};
ErrorResponse.ts:
export default class ErrorResponse {
public desc = "";
public args: any;
public code: string = "";
public message: string = "";
constructor(message, code, desc, args) {
this.message = message;
this.desc = desc;
this.args = args;
this.code = code;
}
}
controller.test.ts:
import { GetPartnerByPKController } from "./controller";
import { partnerDao } from "./AppFactory";
import sinon from "sinon";
import { expect } from "chai";
import ErrorResponse from "./ErrorResponse";
describe("GetPartnerByPKController", () => {
afterEach(() => {
sinon.restore();
});
it("should get parter by uuid correctly", async () => {
const mResponse = "fake data";
const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").resolves(mResponse);
const mReq = { params: { uuid: "123" } };
const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
await GetPartnerByPKController(mReq, mRes);
sinon.assert.calledWith(mRes.status, 200);
sinon.assert.calledWith(mRes.status().send, mResponse);
sinon.assert.calledWith(getPartnerByUuidStub, "123");
});
it("should 404", async () => {
const mResponse = undefined;
const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").resolves(mResponse);
const mReq = { params: { uuid: "123" } };
const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
await GetPartnerByPKController(mReq, mRes);
sinon.assert.calledWith(mRes.status, 404);
sinon.assert.calledWith(
mRes.status().send,
new ErrorResponse("Partner not found", "404.1.100", "ERROR_LINK" + "404.1.100", []),
);
sinon.assert.calledWith(getPartnerByUuidStub, "123");
});
it("should 500", async () => {
const mError = new Error("unknown error");
const getPartnerByUuidStub = sinon.stub(partnerDao, "getPartnerByUuid").rejects(mError);
const mReq = { params: { uuid: "123" } };
const mRes = { status: sinon.stub().returnsThis(), send: sinon.stub() };
await GetPartnerByPKController(mReq, mRes);
sinon.assert.calledWith(mRes.status, 500);
sinon.assert.calledWith(
mRes.status().send,
new ErrorResponse("Internal Server Error", "500.1.103", "ERROR_LINK" + "500.1.103", [
JSON.stringify(mError.message),
]),
);
sinon.assert.calledWith(getPartnerByUuidStub, "123");
});
});
Unit test result with coverage report:
GetPartnerByPKController
Entering GetPartnerByPKController()
Entering GetPartnerByPKController()123
TimeTaken:DBCall:: 21.633ms
Leaving GetPartnerByPKController()
✓ should get parter by uuid correctly
Entering GetPartnerByPKController()
Entering GetPartnerByPKController()123
Partner for the uuid:123 was not found
TimeTaken:DBCall:: 0.532ms
Leaving GetPartnerByPKController()
✓ should 404
Entering GetPartnerByPKController()
Entering GetPartnerByPKController()123
Error in accessing GetPartnerByPK API {}
Error in accessing GetPartnerByPK API {}
TimeTaken:DBCall:: 35.619ms
Leaving GetPartnerByPKController()
✓ should 500 (38ms)
3 passing (124ms)
--------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------------|----------|----------|----------|----------|-------------------|
All files | 98.51 | 100 | 91.67 | 98.41 | |
AppFactory.ts | 50 | 100 | 0 | 50 | 3 |
ErrorResponse.ts | 100 | 100 | 100 | 100 | |
controller.test.ts | 100 | 100 | 100 | 100 | |
controller.ts | 100 | 100 | 100 | 100 | |
--------------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59319054

How to mock response from service for testing controller in typescript using Jest

I am testing a controller written in typescript using Jest. I try to mock the response of the service, but it does not work out.
this is my EmployeesController
import { EmployeesService } from '../services/employeeService';
import { IDBConnection } from '../config/IDBConnection';
export class EmployeesController {
private employeeService: EmployeesService;
constructor(dbConnection: IDBConnection) {
this.employeeService = new EmployeesService(dbConnection);
}
public async findAllEmployees(req: any, res: any) {
const numPerPage = +req.query.pagesize;
const page = +req.query.page;
try {
const count = await this.employeeService.findCount();
const results = await this.employeeService.findAll(numPerPage, page);
let totalEmployee = count[0].totalCount;
if (totalEmployee === 0) {
return res.status(404).json({
success: false,
message: 'Employee not found'
});
} else if (count && results) {
return res.status(200).json({
employees: results,
maxEmployees: totalEmployee
});
};
} catch {
res.status(500).json({
success: false,
message: 'Server error'
});
};
}
this is my EmployeesService
import { IDBConnection } from '../config/IDBConnection';
export class EmployeesService {
private connection: any;
constructor(connection: IDBConnection) {
this.connection = connection;
}
async findCount() {
const results = await this.connection.execute('SELECT count(*) as totalCount FROM EmployeeDB.Employees');
return results; // [ RowDataPacket { totalCount: 5 } ]
}
}
I can assume I am piping to it incorrectly from my service in test but I am not too sure. Is anyone able to help me?
this is my Employee.test
jest.mock('../../../services/employeeService');
import { EmployeesController } from '../../../controllers/employeeController';
import { EmployeesService } from '../../../services/employeeService';
describe('Employees', () => {
test('should get count of employees', async () => {
const getCount = jest.spyOn(EmployeesService.prototype, "findCount")
.mockImplementation(() => Promise.resolve([{totalCount: 5}]));
const mockResp = () => {
const res: any = {}
res.status = jest.fn().mockReturnValue(res)
res.json = jest.fn().mockReturnValue(res)
return res
}
const mockReq = () => {
const req: any = {}
req.query = jest.fn().mockReturnValue(req);
return req
}
const req = mockReq({
pagesize: 1,
page: 0
});
const res = mockResp();
await EmployeesController.prototype.findAllEmployees(req, res);
expect(getCount).toHaveBeenCalledTimes(1); // Received number of calls: 0
}
}
Here is the unit test solution:
controllers/employeeController.ts:
import { EmployeesService } from '../services/employeeService';
import { IDBConnection } from '../config/IDBConnection';
export class EmployeesController {
private employeeService: EmployeesService;
constructor(dbConnection: IDBConnection) {
this.employeeService = new EmployeesService(dbConnection);
}
public async findAllEmployees(req: any, res: any) {
const numPerPage = +req.query.pagesize;
const page = +req.query.page;
try {
const count = await this.employeeService.findCount();
const results = await this.employeeService.findAll(numPerPage, page);
let totalEmployee = count[0].totalCount;
if (totalEmployee === 0) {
return res.status(404).json({
success: false,
message: 'Employee not found',
});
} else if (count && results) {
return res.status(200).json({
employees: results,
maxEmployees: totalEmployee,
});
}
} catch {
res.status(500).json({
success: false,
message: 'Server error',
});
}
}
}
services/employeeService.ts:
import { IDBConnection } from '../config/IDBConnection';
export class EmployeesService {
private connection: any;
constructor(connection: IDBConnection) {
this.connection = connection;
}
async findCount() {
const results = await this.connection.execute('SELECT count(*) as totalCount FROM EmployeeDB.Employees');
return results; // [ RowDataPacket { totalCount: 5 } ]
}
async findAll(numPerPage, page) {
return [];
}
}
config/IDBConnection.ts:
export interface IDBConnection {}
Employee.test.ts:
import { EmployeesController } from './controllers/employeeController';
import { EmployeesService } from './services/employeeService';
jest.mock('./services/employeeService', () => {
const mEmployeesService = {
findCount: jest.fn(),
findAll: jest.fn(),
};
return { EmployeesService: jest.fn(() => mEmployeesService) };
});
describe('Employees', () => {
afterEach(() => {
jest.resetAllMocks();
});
test('should get count of employees', async () => {
const mIDBConnection = {};
const employeeService = new EmployeesService(mIDBConnection);
(employeeService.findCount as jest.MockedFunction<any>).mockResolvedValueOnce([{ totalCount: 5 }]);
(employeeService.findAll as jest.MockedFunction<any>).mockResolvedValueOnce([{ id: 1, name: 'john' }]);
const mReq = {
query: {
pagesize: 10,
page: 1,
},
};
const mRes = {
status: jest.fn().mockReturnThis(),
json: jest.fn(),
};
const employeesController = new EmployeesController(mIDBConnection);
await employeesController.findAllEmployees(mReq, mRes);
expect(employeeService.findCount).toHaveBeenCalledTimes(1);
expect(employeeService.findAll).toBeCalledWith(10, 1);
expect(mRes.status).toBeCalledWith(200);
expect(mRes.status().json).toBeCalledWith({ employees: [{ id: 1, name: 'john' }], maxEmployees: 5 });
});
});
Unit test result with coverage report:
PASS src/stackoverflow/59235639/Employee.test.ts (11.243s)
Employees
✓ should get count of employees (13ms)
-----------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------------------|----------|----------|----------|----------|-------------------|
All files | 88.89 | 66.67 | 100 | 86.67 | |
employeeController.ts | 88.89 | 66.67 | 100 | 86.67 | 18,29 |
-----------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.958s
Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59235639

Resources