Mocking Inherited Classes with Jest - node.js

I am extending net.Socket. In doing so, I am overriding the connect method as follows.
class ENIP extends Socket {
constructor() {
super();
this.state = {
session: { id: null, establishing: false, established: false },
error: { code: null, msg: null }
};
}
connect(IP_ADDR) {
const { registerSession } = encapsulation; //returns a buffer to send
this.state.session.establishing = true;
return new Promise(resolve => {
super.connect(EIP_PORT, IP_ADDR, () => { // This is what i want to mock -> super.connect
this.state.session.establishing = false;
this.write(registerSession());
resolve();
});
});
}
}
I want to mock the underlying Socket class so that I can simulate super.connect. Having viewed Facebook's docs on the matter, I am unsure on how to proceed with developing tests for this class as all methods will extend super.someMethodToMock. Does anyone know an approach I should take? Please let me know if there are any clarifying details I can provide.

You can use jest.spyOn(object, methodName) to create mock methods on Socket.prototype.
E.g.
index.js:
import { Socket } from 'net';
const EIP_PORT = 3000;
const encapsulation = {
registerSession() {
return 'session';
},
};
export class ENIP extends Socket {
constructor() {
super();
this.state = {
session: { id: null, establishing: false, established: false },
error: { code: null, msg: null },
};
}
connect(IP_ADDR) {
const { registerSession } = encapsulation;
this.state.session.establishing = true;
return new Promise((resolve) => {
super.connect(EIP_PORT, IP_ADDR, () => {
this.state.session.establishing = false;
this.write(registerSession());
resolve();
});
});
}
}
index.test.js:
import { ENIP } from './';
import { Socket } from 'net';
describe('ENIP', () => {
afterAll(() => {
jest.restoreAllMocks();
});
describe('#connect', () => {
it('should pass', async () => {
const writeSpy = jest.spyOn(Socket.prototype, 'write').mockImplementation();
const connectSpy = jest.spyOn(Socket.prototype, 'connect').mockImplementationOnce((port, addr, callback) => {
callback();
});
const enip = new ENIP();
await enip.connect('localhost');
expect(writeSpy).toBeCalledWith('session');
expect(connectSpy).toBeCalledWith(3000, 'localhost', expect.any(Function));
});
});
});
unit test result with coverage report:
PASS src/stackoverflow/48888509/index.test.jsx (10.43s)
ENIP
#connect
✓ should pass (7ms)
-----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
index.jsx | 100 | 100 | 100 | 100 | |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 12.357s
source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/48888509

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 Mock MongoDB ( mongoClient ) With Jest

I have a DBManager class to connect to mongoClient
import { MongoClient } from 'mongodb';
class DBManager {
private url = process.env.MONGODB_URL;
private _connection: MongoClient;
constructor() {
this._connection = null;
}
get connection() {
return this._connection;
}
async start() {
if (!this._connection) {
this._connection = await MongoClient.connect(this.url);
}
}
}
export default new DBManager();
and I call this class like this
await DBManager.start();
const db = DBManager.connection.db();
I get this error when I try to mock:
Received: [TypeError: db_manager_1.default.connection.db is not a function]
this is how to mock method i use:
DBManager.start = jest.fn().mockResolvedValue(() => ({
connection: jest.fn().mockReturnThis(),
db: jest.fn().mockResolvedValue({success: true})
}));
thanks..
You can use a real MongoDB server to use in tests with the package mongodb-memory-server.
So in your case, you just need to do:
import { MongoMemoryServer } from '../index';
describe('Single MongoMemoryServer', () => {
let con;
let mongoServer;
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create();
process.env.MONGODB_URL = mongoServer.getUri();
});
afterAll(async () => {
if (con) {
await con.close();
}
if (mongoServer) {
await mongoServer.stop();
}
});
it('DBManager connection', async () => {
await DBManager.start();
const db = DBManager.connection.db();
// ...
});
You can use jest.spyOn(object, methodName, accessType?) to mock DBManager.start() method and DBMananger.connection getter.
E.g.
dbManager.ts:
import { MongoClient } from 'mongodb';
class DBManager {
private url = process.env.MONGODB_URL || '';
private _connection: MongoClient | null;
constructor() {
this._connection = null;
}
get connection() {
return this._connection;
}
async start() {
if (!this._connection) {
this._connection = await MongoClient.connect(this.url);
}
}
}
export default new DBManager();
main.ts:
import DBManager from './dbManager';
export async function main() {
await DBManager.start();
const db = DBManager.connection!.db();
db.collection('users');
}
main.test.ts:
import { main } from './main';
import DBManager from './dbManager';
import { Db, MongoClient } from 'mongodb';
describe('68888424', () => {
afterEach(() => {
jest.restoreAllMocks();
});
test('should pass', async () => {
const mockDbInstance = ({
collection: jest.fn(),
} as unknown) as Db;
const mockDb = jest.fn(() => mockDbInstance);
jest.spyOn(DBManager, 'start').mockResolvedValueOnce();
jest.spyOn(DBManager, 'connection', 'get').mockReturnValue(({ db: mockDb } as unknown) as MongoClient);
await main();
expect(DBManager.start).toBeCalledTimes(1);
expect(DBManager.connection!.db).toBeCalledTimes(1);
expect(mockDbInstance.collection).toBeCalledWith('users');
});
});
test result:
PASS examples/68888424/main.test.ts (8.621 s)
68888424
✓ should pass (5 ms)
--------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------|---------|----------|---------|---------|-------------------
All files | 75 | 50 | 50 | 75 |
dbManager.ts | 57.14 | 50 | 33.33 | 57.14 | 12-17
main.ts | 100 | 100 | 100 | 100 |
--------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.532 s

Jest mock for redis-sessions functions

I want to mock the redis-session function.
static async createSession(userData: string, userId: Uuid, ipAddress: string = 'NA'): Promise<string> {
try {
const rs = this.getRedisConnection();
return new Promise<string>((resolve, reject): void => {
rs.create(
{
app: Configs.rsSessionApp,
id: userId,
ip: ipAddress,
ttl: Configs.rsDefaultTtl,
d: {
data: userData,
},
},
(err: object, resp: { token: string }): void => {
if (resp !== undefined && resp.token.length > 0) {
return resolve(resp.token);
}
if (err != null) {
reject(err);
}
},
);
});
} catch (error) {
return Promise.reject(error.message);
}
}
I want to make this line execute (err: object, resp: { token: string }): void => {}
How to achieve or resolve this using jest unit test?.
Another unit test to throw the error.
try...catch... cannot catch the exception of asynchronous code, you can remove it.
You can use jest.spyOn(object, methodName) to mock RedisSession.getRedisConnection() method and return a mocked redis connection. Then, mock the implementation of rs.create() method, you can get the anonymous callback function in your test case.
At last, call the anonymous callback function manually with mocked arguments.
E.g.
index.ts:
import RedisSessions from 'redis-sessions';
interface Uuid {}
export class RedisSession {
static async createSession(userData: string, userId: Uuid, ipAddress: string = 'NA'): Promise<string> {
const rs = this.getRedisConnection();
return new Promise<string>((resolve, reject): void => {
rs.create(
{
app: 'test',
id: userId,
ip: ipAddress,
ttl: 3600,
d: {
data: userData,
},
},
(err: object, resp: { token: string }): void => {
if (resp !== undefined && resp.token.length > 0) {
return resolve(resp.token);
}
if (err != null) {
reject(err);
}
}
);
});
}
static getRedisConnection() {
return new RedisSessions({ host: '127.0.0.1', port: '6379', namespace: 'rs' });
}
}
index.test.ts:
import { RedisSession } from './';
describe('67220364', () => {
it('should create redis connection', async () => {
const mRs = {
create: jest.fn().mockImplementationOnce((option, callback) => {
callback(null, { token: '123' });
}),
};
const getRedisConnectionSpy = jest.spyOn(RedisSession, 'getRedisConnection').mockReturnValueOnce(mRs);
const actual = await RedisSession.createSession('teresa teng', '1');
expect(actual).toEqual('123');
expect(getRedisConnectionSpy).toBeCalledTimes(1);
expect(mRs.create).toBeCalledWith(
{
app: 'test',
id: '1',
ip: 'NA',
ttl: 3600,
d: {
data: 'teresa teng',
},
},
expect.any(Function)
);
});
});
unit test result:
PASS examples/67220364/index.test.ts (8.636 s)
67220364
✓ should create redis connection (5 ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 70 | 57.14 | 75 | 70 |
index.ts | 70 | 57.14 | 75 | 70 | 24-33
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.941 s

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