how to test a Module in NodeJs without function in it? - node.js

I have read and tried many ways to do this,I have a module like below .
//echo.js
module.exports = (services, request) => {
logger.debug('excecuting');
return true;
};
I want to write unit test for this module using sinon , what i did tried so far is.
describe('test', function() {
const echo1 = require('./echo');
var spy1 = sinon.spy(echo1);
beforeEach(() => {
spy1.resetHistory();
});
it('Is function echo called once - true ', done => {
echo1(testData.mockService, testData.stubRequest); //calling module
spy1.called.should.be.true;
done();
});
});
i get the below output which is failed, though i see my function being called in the output window
1) test
Is function echo called once - true :
AssertionError: expected false to be true
+ expected - actual
-false
+true
at Context.done (echo_unit.js:84:27)
could anyone tell me how to test modules in nodejs

It doesn't matter in this case whether it's a module or just a function.
A function that isn't called as a method can't be spied (also, describe function isn't a proper place to place var spy1 = sinon.spy(echo1)). This also isn't needed here because it's you who call the function, there's no need to test that it was called.
Since all that echo does is calls logger.debug and returns true, this needs to be tested:
it('Is function echo called once - true ', () => {
sinon.spy(logger, 'debug');
const result = echo1(testData.mockService, testData.stubRequest);
expect(logger.debug).to.have.been.calledWith("execute");
expect(result).to.be(true);
// the test is synchronous, no done() is needed
});

Related

NodeJS Unit test how to spy/stub

I am stuck on this for few days now.
while testing my handler function I would like to "fake" the call to rotateApiKeys fonction I was thinking to use stubs to achieve that.
But first I would like to see if at least I could spy on rotateApiKeys while calling the handler, so far I am getting:
AssertError: expected rotateApiKeys to be called once but was called 0 times and I can see that function actually been called.
Questions:
What would you recommend me to use? Mock/Stub/Spy
If Spy should work, why I am getting that assertError?
Handler:
async function handler(event) {
// declare a new JSON object
let handlerObject = {
"event": event,
"isValidEvent": rotateFunctions.validateEvent(event),
"actionCountObject": {}
};
if (handlerObject.isValidEvent) {
// continue here
handlerObject.actionCountObject = await rotateApiKeys(event);
}
// console log JSON handlerObject
console.log("handlerObject: " + JSON.stringify(handlerObject));
// return the object
return handlerObject;
}
unit test code:
it("Should call rotate", async function() {
var rotate = sinon.spy(rotateApiKeys, 'rotateApiKeys');
const result = await rotateApiKeys.handler(event);
rotate.restore();
sinon.assert.calledOnce(rotate);
});

importing and calling a function in Typsescript which returns nothing

Hi I have a function in typescript which returns nothing. When I try to import and call this function in another part of my app, I am getting errors. I am fairly new to typescript and am struggling with how to fix this issue.
Here's my code. I am trying to set up a few scripts to do some simple tests (would prefer not to use any testing frameworks).
My helper functions for testing are here
//File: helper.ts
type validator = () => void;
export const it = (desc: string, fn: validator) => {
try {
let res = fn();
console.log("\x1b[32m%s\x1b[0m", `\u2714 ${desc}`);
} catch (error) {
console.log("\n");
console.log("\x1b[31m%s\x1b[0m", `\u2718 ${desc}`);
console.error(error);
}
};
My tests use the helpers and are defined like this;
// File: dummytests.ts
import { strict as assert } from 'node:assert';
import { it } from "src/spec/helper";
export const check_if15_eqls_15 = it("shoulld check if something is true", () => {
assert.strictEqual(15, 15);
});
and i finally am running the tests as such;
// File: testRUnner.ts
import {check_if15_eqls_15} from 'src/spec/frontend/dummyTests';
console.log ("This test harness is for the frontend tests.\n");
check_if15_eqls_15();
this throws the error;
error TS2349: This expression is not callable.
Type 'void' has no call signatures.
5 check_if15_eqls_15();
~~~~~~~~~~~~~~~~~~
The line
export const check_if15_eqls_15 = it("shoulld check if something is true", () => {
assert.strictEqual(15, 15);
});
already calls the method.
This means check_if15_eqls_15 is already the return value of the method and unless the return value is not another function (which it isn't in this case), you can't call it again.
The same thing would happen in pure JS, since TypeScript does not change how the code is run
Something that might work for your example would be this:
export const check_if15_eqls_15 = () => it("shoulld check if something is true", () => {
assert.strictEqual(15, 15);
});

Failing to mock declared functions with jest.spyOn

I'm under the impression that jest.spyOn.mockImplementationOnce can mock a function as long as it is implemented as a function expression, but might fail to mock when the function is written as a function declaration. Why is it behaving like that?
I have one TS file in the folder */this_works with the following code:
export function myFunction() {
return myOtherFunction();
}
export const myOtherFunction = function() {
return 'something';
};
And then another TS file in the folder */this_doesnt with the following code:
export function myFunction() {
return myOtherFunction();
}
export function myOtherFunction() {
return 'something';
}
The only difference between them is that myOtherFunction is either a function declaration or a function expression.
Both files are submitted to the same test with jest.
import * as myModule from '../index';
describe('myFunction', () => {
it('does something', () => {
jest
.spyOn(myModule, 'myOtherFunction')
.mockImplementationOnce(
function() {
return 'hello jest';
},
);
const result = myModule.myFunction();
expect(result).toEqual('hello jest');
});
});
All code can be found at my playground repo's folder
The result is that the function expression is mocked and the test passes, while the function declaration is not mocked and the test fails.
Anecdotally, this seems to only happen if the function being mocked is not being called directly, instead it is being called by another function. When the declared function gets called directly, the test passes.
I would like to understand why that is so I can write better tests.

How to do callback in our component using react jest test cases

How can we do callback on success and failue cases for below lines of code for test coverage using jest
const handleService = () => {
window.domain.service("1321",'',onSuccess, onFailure)
}
const onSuccess = () => {
....update state values
}
const onFailure = () => {
....update state values
}
Something like this:
Spy on window.domain.service to gain access to the calls it receives. This will allow you to access the parameters of those calls which will be "1321",'',onSuccess, onFailure
Assign the function you wish to test to a variable
Invoke the function to execute the code in it (this will get you the coverage)
(Optional) assert that the callback functions behave correctly
Here is a snippet to help demonstrate
it('should run', () => {
// Some setup to create the function on the window, may not be needed if done elsewhere.
// Could be good to do this in a beforeEach and clean up in afterEach to avoid contaminating the window object
window.domain = {
service: () => {},
}
// Spy on the window.domain.service method.
// Provide a mock implementation if you don't want the real one to be called
const serviceSpy = jest.spyOn(window.domain, 'service');
executeYourCode();
// capture the arguments to the call
const [_arg1, _arg2, onSuccess, onFailure] = serviceSpy.mock.calls[0];
// execute the callbacks
onSuccess();
onFailure();
});

Mock function without callback as parameter

I have dh.js
const checkDExistsCallback = (err, dResp) => {
if (err)
cbResp.error('failed');
if (dResp.length > 0)
checkDCollectionExists();
else
cbResp.error('Not found.');
};
const checkDCollectionExists = () =>
{
let query = `select sid from tablename where sid = '${objRequestData.dName}' limit 1;`;
genericQueryCall(query, checkDCollCallback);
}
module.exports = {checkDExistsCallback , checkDCollectionExists }
In my dh.test.ts
const dhExport = require("./DensityHookReceive");
dhExport.checkDCollectionExists = jest.fn().mockImplementation(() => {});
test('check req dh is exists', () => {
dhExport.checkDExistsCallback(false, '[{}]');
expect(dhExport.checkDCollectionExists).toBeCalled();
});
In dh.js checkDExistsCallback function is invoked the checkDCollectionExists after satisfied the 'if' condition. When you look into the dh.test.ts file I mocked the checkDCollectionExists function in the beginning, but while running the test it did not invoke the mocked function it invokes the actual function. Can you help me to figure it out?
A function that is used in the same module it was defined cannot be mocked, unless it's consistently used as a method on an object that could be mocked, e.g.
if (dResp.length > 0)
module.exports.checkDCollectionExists();
instead of
if (dResp.length > 0)
checkDCollectionExists();
checkDCollectionExists needs to be either moved to another module, or two functions need to be tested as a single unit. It's database call that needs to be mocked.

Resources