Jasmine - Spy on a function that is called in same file - node.js

This has bothered me for a while. I have two functions in the same file.
//fun.ts
export function fun1(){
let msg = fun2();
return msg;
}
export function fun2(): string{
return "Some message";
}
I have a typescript spec that stubs fun2 and calls fun1.
//fun.spec.ts
import * as Fun from 'fun';
describe('Stubing', () => {
it('should stub the return value', () => {
spyOn(Fun, 'fun2').and.returnValue("A different message");
expect(Fun.fun1()).toEqual("A different message")
});
});
But when I run the spec, the output I get is
Failures:
1) Stubing should stub the return value
1.1) Expected 'Some message' to equal 'A different message'.
I wrote the tests in typescript and then I have a gulp script that successfully transpiles and runs the jasmine specs. Everything works, the only thing that I can't figure out is why the spy is not working. An explanation would be appreciated.

I finally figured this out. In fun.ts, I am directly calling the fun2 object, but my Jasmine spec has no access to that object. The only object the Jasmine spec can access is the exports object. If I want the spy to work I need to call fun2 on the exports object.
//fun.ts
export function fun1(){
let msg = exports.fun2();
console.log(msg);
}
export function fun2(): string{
return "Some message";
}
Now when the spec executes I see
.
1 spec, 0 failures

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 test a Module in NodeJs without function in it?

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

How to test bootstrap methods in node?

I have a react component that has the following line in componentDidMount():
$('[data-toggle="tooltip"]').tooltip();
When I run my test, I get:
TypeError: $(...).tooltip is not a function
I have global.$ defined, but I wonder if there is a way to stub out the tooltip() function when my tests are run. I don't care if the tooltip() is stubbed, I just need my test to run.
Any help would be appreciated!
ask global.$ to return object with a .tooltip function
global.$ = function () {
return {
tooltip: function() { console.log(42) }
}
}

Resources