How to check if mocked inner function has been called in jest? - javascript

here is my file under test:
file.js:
function handleRequest(grpcRequestObj, callback){
if(grpcRequestObj.type === REAL_CLIENT_REQUEST){
log.trace("Запрос от реального клиента", refId);
module.exports.realClientRequestWay(grpcRequestObj, callback);
return;
}
}
function realClientRequestWay(grpcRequestObj, callback){
//some logic
}
module.exports = {
handleRequest,
realClientRequestWay
}
test file:
test("should call real clients way", ()=>{
jest.mock("../lib/grpc/state");
const state = require("../lib/grpc/state");
state.ready = true;
const constants = require("../lib/grpc/constants");
const handleRequestModule = require("../lib/grpc/handleRequest");
const { handleRequest } = jest.requireActual("../lib/grpc/handleRequest");
handleRequestModule.realClientRequestWay = jest.fn();
const grpcRequest = {
type: constants.REAL_CLIENT_REQUEST,
refId: "123"
};
const mockCb = jest.fn();
handleRequest(grpcRequest, mockCb);
expect(handleRequestModule.realClientRequestWay).toHaveBeenCalledTimes(1);
});
I am mocking realClientRequestWay fucntion to be a jest mock function just to check if it runs,
but it is not calling, what am I doing wrong?

You can use jest.spyOn(object, methodName) and mockImplementation to overwrite the original function with a mocked one.
E.g.
file.js:
const log = { trace: console.log };
const REAL_CLIENT_REQUEST = 'REAL_CLIENT_REQUEST';
function handleRequest(grpcRequestObj, callback) {
const refId = '1';
if (grpcRequestObj.type === REAL_CLIENT_REQUEST) {
log.trace('Запрос от реального клиента', refId);
module.exports.realClientRequestWay(grpcRequestObj, callback);
return;
}
}
function realClientRequestWay(grpcRequestObj, callback) {
//some logic
}
module.exports = {
handleRequest,
realClientRequestWay,
};
file.test.js:
const file = require('./file');
describe('62079376', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should request', () => {
jest.spyOn(file, 'realClientRequestWay').mockImplementationOnce();
const mCallback = jest.fn();
file.handleRequest({ type: 'REAL_CLIENT_REQUEST' }, mCallback);
expect(file.realClientRequestWay).toBeCalledWith({ type: 'REAL_CLIENT_REQUEST' }, mCallback);
});
it('should do nothing if type not match', () => {
jest.spyOn(file, 'realClientRequestWay').mockImplementationOnce();
const mCallback = jest.fn();
file.handleRequest({ type: '' }, mCallback);
expect(file.realClientRequestWay).not.toBeCalled();
});
});
unit test results with 100% coverage:
PASS stackoverflow/62079376/file.test.js (10.044s)
62079376
✓ should request (16ms)
✓ should do nothing if type not match (1ms)
console.log
Запрос от реального клиента 1
at Object.handleRequest (stackoverflow/62079376/file.js:7:9)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
file.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 11.393s, estimated 12s

Related

nodejs Jest testing exec.stdout.on('data',data)

Trying to to test a function the incorporates the exec of child_process library.
const { exec } = require('child_process')
const randomFunc = () => {
const newSync = exec('some command to execute')
newSync.stdout.on('data', data => {
console.log(data.toString())
})
}
testfile:
const {randomFunc} = require(randomFuncFile)
const { exec } = require('child_process')
jest.mock('child_process')
it('test', () => {
const readStreamObject = {
on: jest.fn().mockImplementation(function (event, handler) {
handler('streaming ')
})
}
exec.mockImplementation(data => ({stdout: readStreamObject})
randomFunc()
expect(exec.stdout.on).toHaveBeenCalled()
}
I'm getting
TypeError: Cannot read properties of undefined (reading 'on')
some tips would be great.
You can get the mock stdout returned by mocked exec() function via exec.mock.results[0].value.stdout, See mockFn.mock.results
index.js:
const { exec } = require('child_process');
const randomFunc = () => {
const newSync = exec('some command to execute');
newSync.stdout.on('data', (data) => {
console.log(data.toString());
});
};
module.exports = { randomFunc };
index.test.js:
const { exec } = require('child_process');
const { randomFunc } = require('./');
jest.mock('child_process');
it('test', () => {
const mStdout = {
on: jest.fn().mockImplementation(function (event, handler) {
handler('streaming');
}),
};
exec.mockImplementation(() => ({ stdout: mStdout }));
randomFunc();
// expect(mStdout.on).toHaveBeenCalled();
// or
expect(exec.mock.results[0].value.stdout.on).toHaveBeenCalled();
});
Test result:
PASS stackoverflow/75036469/index.test.js (8.403 s)
✓ test (15 ms)
console.log
streaming
at stackoverflow/75036469/index.js:6:13
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 9.016 s

how to jest mock for a custom library

abc.js
import { form } from '#myCustomLib/validator'
const _validator = new form.particulars.Validator()
function sampleFunctionIWantToTest(formInfo) {
var error = _validator.fullValidation(formInfo)
if(error) {return true}
return false
}
I want to write a test for the function. I would like to mock the result for
_validator.fullValidation(formInfo)
How do I mock?
You can use jest.mock(moduleName, factory, options) to mock #myCustomLib/validator package.
E.g.
abc.js:
import { form } from '#myCustomLib/validator';
const _validator = new form.particulars.Validator();
function sampleFunctionIWantToTest(formInfo) {
var error = _validator.fullValidation(formInfo);
if (error) {
return true;
}
return false;
}
export { sampleFunctionIWantToTest };
abc.test.js:
import { form } from '#myCustomLib/validator';
const validatorMock = {
fullValidation: jest.fn(),
};
jest.mock(
'#myCustomLib/validator',
() => {
const formMock = {
particulars: {
Validator: jest.fn(() => validatorMock),
},
};
return { form: formMock };
},
{ virtual: true },
);
describe('62949328', () => {
afterAll(() => {
jest.resetAllMocks();
});
it('should return true', () => {
const mError = new Error('error message');
validatorMock.fullValidation.mockReturnValueOnce(mError);
const { sampleFunctionIWantToTest } = require('./abc');
const actual = sampleFunctionIWantToTest();
expect(actual).toBeTruthy();
expect(form.particulars.Validator).toBeCalledTimes(1);
});
it('should return false', () => {
validatorMock.fullValidation.mockReturnValueOnce(null);
const { sampleFunctionIWantToTest } = require('./abc');
const actual = sampleFunctionIWantToTest();
expect(actual).toBeFalsy();
expect(form.particulars.Validator).toBeCalledTimes(1);
});
});
unit test result with 100% coverage:
PASS stackoverflow/62949328/abc.test.js (13.298s)
62949328
✓ should return true (6ms)
✓ should return false (1ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
abc.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 15.161s
jestjs version: "jest": "^25.5.4",

Jest: Mock class method in a function

So just trying to understand how I mock a class function within a function itself. How do I mock the data returned from the exchange.someFunction() method so I can test the actual getPositions() function itself?
const library = require('library');
const exchange = new library.exchange_name();
async function getPositions() {
let positions = [];
const results = await exchange.someFunction();
// Do some stuff
return results;
}
I was trying to do the following but have no idea if I'm doing anything correct at all
const exchange = require('../../exchange');
jest.mock('library')
it('get balances', async () => {
library.someFunction.mockResolvedValue({
data: [{some data here}]
)}
}
Error thrown:
TypeError: Cannot read property 'mockResolvedValue' of undefined
Here is the unit test solution:
index.js:
const library = require('./library');
const exchange = new library.exchange_name();
async function getPositions() {
let positions = [];
const results = await exchange.someFunction();
return results;
}
module.exports = getPositions;
library.js:
function exchange_name() {
async function someFunction() {
return 'real data';
}
return {
someFunction,
};
}
module.exports = { exchange_name };
index.test.js:
const getPositions = require('./');
const mockLibrary = require('./library');
jest.mock('./library', () => {
const mockExchange = { someFunction: jest.fn() };
return { exchange_name: jest.fn(() => mockExchange) };
});
describe('61649788', () => {
it('get balances', async () => {
const mockExchange = new mockLibrary.exchange_name();
mockExchange.someFunction.mockResolvedValueOnce({ data: ['mocked data'] });
const actual = await getPositions();
expect(actual).toEqual({ data: ['mocked data'] });
expect(mockExchange.someFunction).toBeCalled();
});
});
unit test results with 100% coverage:
PASS stackoverflow/61649788/index.test.js (8.775s)
61649788
✓ get balances (7ms)
----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
index.js | 100 | 100 | 100 | 100 |
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.099s

How to mock object creation and its method

new UrlBuilder(urlString).buildURL(params).getShortenedURL().then(data => {
.....
});
How can I stub the object creation and check whether getShortenedURL() has been called?
I tried
this.urlBuilder = sinon.stub(UrlBuilder.prototype, getShortenedURL).resolves({url: '/someUrl'});
But every time I run a test that has:
assert(this.urlBuilder.getShortenedURL.called);
it'll say
ReferenceError: getShortenedURL is not defined
Here is the unit test solution:
index.js:
const UrlBuilder = require('./urlBuilder');
function main() {
const urlString = 'https://stackoverflow.com/';
const params = {};
return new UrlBuilder(urlString)
.buildURL(params)
.getShortenedURL()
.then((data) => data);
}
module.exports = main;
urlBuilder.js:
class UrlBuilder {
constructor(url) {
this.url = url;
}
buildURL(params) {
return this;
}
getShortenedURL() {
return Promise.resolve('real data');
}
}
module.exports = UrlBuilder;
index.test.js:
const sinon = require('sinon');
const proxyquire = require('proxyquire');
const { expect } = require('chai');
describe('60214679', () => {
it('should pass', async () => {
const urlBuilderInstanceStub = {
buildURL: sinon.stub().returnsThis(),
getShortenedURL: sinon.stub().resolves('fake data'),
};
const urlBuilderStub = sinon.stub().callsFake(() => urlBuilderInstanceStub);
const main = proxyquire('./', {
'./urlBuilder': urlBuilderStub,
});
const actual = await main();
expect(actual).to.be.eq('fake data');
sinon.assert.calledWithExactly(urlBuilderStub, 'https://stackoverflow.com/');
sinon.assert.calledWithExactly(urlBuilderInstanceStub.buildURL, {});
sinon.assert.calledOnce(urlBuilderInstanceStub.getShortenedURL);
});
});
Unit test results with coverage report:
60214679
✓ should pass (2010ms)
1 passing (2s)
---------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------|---------|----------|---------|---------|-------------------
All files | 70 | 100 | 40 | 70 |
index.js | 100 | 100 | 100 | 100 |
urlBuilder.js | 25 | 100 | 0 | 25 | 3,6,9
---------------|---------|----------|---------|---------|-------------------
Source code: https://github.com/mrdulin/expressjs-research/tree/master/src/stackoverflow/60214679

JestJS: How to test for calling function in a nested (async) function

I'm trying to write a unit test for a nested function, which looks like this:
myFunction.js
const anotherFunction = require('./anotherFunction.js')
module.exports = (app, io) => {
return (req, res) => {
const { id, value } = req.query
req.app.locals['target' + id].pwmWrite(value)
anotherFunction(app, io)
res.send({ value })
}
}
I would like to test if pwmWrite() and anotherFunction() have been called.
But I've got some problems because of the return (req, res) => {} and because of the imported function.
This is my attempt, which is not working:
myFunction.test.js
test('should call pwmWrite() and anotherFunction()', async () => {
const app = {}
const io = { emit: jest.fn() }
const req = {
app: {
locals: {
target1: { pwmWrite: () => 25 }
}
}
}
}
expect.assertions(1)
expect(req.app.locals.target1.pwmWrite).toHaveBeenCalled()
await expect(myFunction(app, io)).resolves.toEqual(25)
})
Here is the solution:
myFunction.js:
const anotherFunction = require('./anotherFunction.js');
module.exports = (app, io) => {
return (req, res) => {
const { id, value } = req.query;
req.app.locals['target' + id].pwmWrite(value);
anotherFunction(app, io);
res.send({ value });
};
};
anotherFunction.js:
module.exports = (app, io) => {
return 'do something';
};
Unit test:
jest.mock('./anotherFunction');
const myFunction = require('./myFunction');
const anotherFunction = require('./anotherFunction');
describe('test suites', () => {
test('should call pwmWrite() and anotherFunction()', () => {
const app = {};
const io = { emit: jest.fn() };
const id = '1';
const value = 'jest';
const req = {
query: { id, value },
app: {
locals: {
target1: { pwmWrite: jest.fn() }
}
}
};
const res = { send: jest.fn() };
myFunction(app, io)(req, res);
expect(anotherFunction).toBeCalledWith(app, io);
expect(req.app.locals.target1.pwmWrite).toBeCalledWith(value);
});
});
Unit test result with coverage report:
PASS src/stackoverflow/52845000/myFunction.spec.js
test suites
✓ should call pwmWrite() and anotherFunction() (5ms)
--------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
--------------------|----------|----------|----------|----------|-------------------|
All files | 88.89 | 100 | 66.67 | 88.89 | |
anotherFunction.js | 50 | 100 | 0 | 50 | 2 |
myFunction.js | 100 | 100 | 100 | 100 | |
--------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 3.113s
Here is the completed demo: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52845000

Categories

Resources