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
Related
I have below mentioned files
|_ utils.js
|_methods.js
I am doing unit testing for rest.js methods, file contents are
methods.js
import Express from 'express'
import { add_rec } from './utils'
export const create_rec = () => async (req: Express.Request, res: Express.Response) => {
const rec_body = req.body.rec
return add_rec(rec_body)
.then((ret) => res.status(201).send(ret))
.catch((e) => {
res.status(500).send({ message: e.message })
})
}
How can mock the add_rec async function so that I can unit-test my create_rec
function
I am trying to test create_rec below way but it is not allowing me to mock add_rec method
mport { getMockReq, getMockRes } from '#jest-mock/express'
import { add_rec } from './utils'
jest.mock('./utils')
describe('test create_rec method valid param', () => {
it('test create_rec method', async () => {
const req = getMockReq({
body: {
rec: {},
},
})
const { res } = getMockRes<any>({
status: jest.fn(),
send: jest.fn(),
})
add_rec.mockResolved({}) // this line is giving error in fact it is not mocked i think
await create_rec()(req, res)
expect(res.status).toHaveBeenCalledTimes(1)
expect(res.send).toHaveBeenCalledTimes(1)
})
})
Please help me with this.
Your code is almost correct, except that you need to do some processing on the TS type of the mock method, you can use type assertion.
E.g.
methods.ts:
import Express from 'express';
import { add_rec } from './utils';
export const create_rec = () => async (req: Express.Request, res: Express.Response) => {
const rec_body = req.body.rec;
return add_rec(rec_body)
.then((ret) => res.status(201).send(ret))
.catch((e) => {
res.status(500).send({ message: e.message });
});
};
utils.ts:
export async function add_rec(params): Promise<any> {
console.log('real implementation');
}
methods.test.ts:
import Express from 'express';
import { create_rec } from './methods';
import { add_rec } from './utils';
jest.mock('./utils');
describe('68419899', () => {
test('should pass', async () => {
(add_rec as jest.MockedFunction<any>).mockResolvedValueOnce({});
const req = ({ body: { rec: {} } } as unknown) as Express.Request;
const res = ({ status: jest.fn().mockReturnThis(), send: jest.fn() } as unknown) as Express.Response;
await create_rec()(req, res);
expect(add_rec).toBeCalledWith({});
expect(res.status).toBeCalledWith(201);
expect(res.send).toBeCalledWith({});
});
});
test result:
PASS examples/68419899/methods.test.ts (8.659 s)
68419899
✓ should pass (5 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 81.82 | 100 | 66.67 | 75 |
methods.ts | 88.89 | 100 | 80 | 83.33 | 10
utils.ts | 50 | 100 | 0 | 50 | 2
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.198 s
My index.ts file looks like this
import {IS3Client, S3Client} from './client/S3Client';
const s3: IS3Client = new S3Client();
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a','b');
}
S3Client.ts looks like this
import * as AWS from 'aws-sdk';
export interface IS3Client {
getFile(bucketName: string, fileName: string): Promise<any>;
}
export class S3Client implements IS3Client {
private s3Client: AWS.S3;
constructor() {
this.s3Client = new AWS.S3();
}
public async getFile(bucketName: string, fileName: string): Promise<any> {
const params = {
Bucket: bucketName,
Key: fileName,
};
return (await this.s3Client.getObject(params).promise()).Body.toString();
}
}
Now I am interested to mock the getFile function to return what I want when I am testing index.ts
My test case looks like this
import {someFunc} from '../src/index';
import { S3Client } from '../src/client/S3Client';
describe("Test Suite", () => {
beforeAll(()=>{
jest.mock('../src/client/S3Client');
const mockedClient: jest.Mocked<S3Client> = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('hello'));
});
it("testCase", () => {
const req = {
"key" : ["value"]
};
someFunc(req, null, null);
})
});
I am getting the following error :
TypeError: mockedClient.getFile.mockImplementation is not a function
Somehow this is looking much harder than I thought. Can someone suggest something, Thanks in advance ?
I added another class like this
import { SecretsManager } from 'aws-sdk';
export default class XUtils {
private secretsManager: SecretsManager;
constructor(secretsManager: SecretsManager) {
this.secretsManager = secretsManager;
}
public async getData(urlPrefix: string): Promise<any[]> {
return ['data'];
}
}
And my index.ts looks something like this :
import {IS3Client, S3Client} from './client/S3Client';
import XUtils from './utils/XUtils';
import { SecretsManager } from 'aws-sdk';
const s3: IS3Client = new S3Client();
const secretsManager: SecretsManager = new SecretsManager({ region: process.env.AWS_REGION });
const xUtils: XUtils = new XUtils(secretsManager)
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a','b');
const y = await xUtils.getData(x);
}
Following from what you suggested, I modified my test case to something like this :
import {someFunc} from '../src/index';
import { S3Client } from '../src/client/S3Client';
import XUtils from '../utils/XUtils';
jest.mock('../src/client/S3Client', () => {
const mS3Client = { getFile: jest.fn() };
return { S3Client: jest.fn(() => mS3Client) };
});
jest.mock('../utils/XUtils', () => {
const mXUtils = { getData: jest.fn() };
return { XUtils: jest.fn(() => mXUtils) };
});
describe("Test Suite", () => {
beforeAll(()=>{
mockedClient = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('url'));
mockedXUtils = new XUtils(null) as any;
mockedXUtils.getData.mockImplementation(() => Promise.resolve(['data']))
});
it("testCase", () => {
const req = {
"key" : ["value"]
};
someFunc(req, null, null);
})
});
I am getting error now as
TypeError: XUtils_1.default is not a constructor
What exactly is this problem ?
You can't use jest.mock in the function scope. It should be used in module scope.
You should use async/await for someFunc method in your test case.
E.g.
index.ts:
import { IS3Client, S3Client } from './s3client';
const s3: IS3Client = new S3Client();
export async function someFunc(event: any, context: any, callback: any) {
const x: string = await s3.getFile('a', 'b');
}
s3client.ts:
import * as AWS from 'aws-sdk';
export interface IS3Client {
getFile(bucketName: string, fileName: string): Promise<any>;
}
export class S3Client implements IS3Client {
private s3Client: AWS.S3;
constructor() {
this.s3Client = new AWS.S3();
}
public async getFile(bucketName: string, fileName: string): Promise<any> {
const params = {
Bucket: bucketName,
Key: fileName,
};
return (await this.s3Client.getObject(params).promise()).Body!.toString();
}
}
index.test.ts:
import { someFunc } from './';
import { S3Client } from './s3client';
jest.mock('./s3client', () => {
const mS3Client = { getFile: jest.fn() };
return { S3Client: jest.fn(() => mS3Client) };
});
describe('Test Suite', () => {
let mockedClient: jest.Mocked<S3Client>;
beforeAll(() => {
mockedClient = new S3Client() as any;
mockedClient.getFile.mockImplementation(() => Promise.resolve('hello'));
});
it('testCase', async () => {
const req = {
key: ['value'],
};
await someFunc(req, null, null);
expect(mockedClient.getFile).toBeCalledWith('a', 'b');
});
});
Unit test results with 100% coverage:
PASS stackoverflow/60445082/index.test.ts (8.548s)
Test Suite
✓ testCase (6ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.04s
source code: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60445082
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
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