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
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!
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));
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 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
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