Jest having trouble mocking specific function - javascript

I've started using jest but I've been having some trouble mocking specific JS functions, I've already tried various would be solutions to this but i just couldn't get it to work.
Below is my JavaScript function code
functions.js :
function test1(){
return "hello1"
}
function test2(){
return "hello2"
}
module.exports = test1;
module.exports = test2;
and this is my jest code:
function.test.js
const testfunction = require('/function');
test('tooltip Correct DOM element test', () => {
expect(testfunction.test1).toBe("hello1");
});

You are exporting the function incorrectly. You need to do:
function test1() {
return "hello1"
}
function test2() {
return "hello2"
}
module.exports = {
test1: test1,
test2: test2
};
Exporting the function in this way will enable to get testfunction.test1 inside the test file. And you need to call the function inside the test script like:
expect(testfunction.test1()).toBe("hello1");

Related

custom global function not defined when testing in Jest; works fine when not testing

I have a custom, globally-scoped function in my Express app, foo. When running my Jest test scripts, this function is caught as undefined. Thus, any tests using them fail.
index.d.ts:
declare global{
function foo(): string;
}
export {};
src/Utils/index.ts:
global.foo = function foo(){
return "bar";
};
src/Modules/Example.module.ts:
export const test = () => {
// This will return bar, as expected, when developing.
// A reference error will only be thrown when running npm test.
return foo();
};
src/Modules/Example.test.ts:
import { test } from "./Example.module";
describe("modules/example", () => {
describe("test", () => {
it("returns bar", () => {
let bar = test();
expect(bar).toBe("bar");
});
});
});
Despite this not being an issue while developing, this test results in the error:
ReferenceError: foo is not defined.
export const test = () => {
return foo();
^
...
};
You can specify src/Utils/index.ts as a setup file, which Jest will load and execute before running tests. You can add it to your Jest configuration file (or create one if you don't have one):
Assuming a CJS-format Jest configuration, jest.config.js:
module.exports = {
// Your other configuration options
"setupFiles": ["<rootDir>/src/Utils/index.ts"]
};
It will look slightly different if you are using a JSON or TypeScript Jest configuration file.
However I don't recommend using global variables (even if you use them a lot). With a proper code editor setup, it is easy to import a function from another file.

how to export javascript function as a module

I've exported a function and imported it in Javascript, but the only way i can access the functions inside it is by typing it like this:
myModule.mainFunc().func1()
But what i'm trying to achieve is more like this:
myModule.mainFunc.func1()
Currently it gives an error if i try to reference to it like this.
I've tried returning the values of the functions as objects but it still needs me to call it as functions.
function greet() {
var hello = () => {
console.log("hello there");
};
var hi = () => {
console.log("hi there");
};
return { hello: hello, hi: hi }; // I've tried this doing it like this
}
export default {greet};
Here's how I'm importing it:
import greetings from "./index.js";
greetings.greet().hello()
define greet as an object
var greet = {
hello: () => {
console.log("hello there");
},
hi: () => {
console.log("hi there");
},
}
and access it like greet.hello()
You can't reference the functions defined inside greet function as
myModule.mainFunc.func1()
because myModule.mainFunc is a greet function itself. What you want to import is the result of calling greet function.
You can avoid invoking the greet function manually by making your function an IIFE (Immediately Invoked Function Expression). Doing this will execute the function as soon as it is defined.
const greet = (function() {
var hello = () => {
console.log("hello there");
};
var hi = () => {
console.log("hi there");
};
return { hello, hi };
})();
export default { greet };
Now when you export greet, you are not exporting greet function, but the result of calling greet function which is an object with two functions, hello and hi.
Which environment you're running your code ? If it's NodeJS, make sure it supports ES6 Module as your current style of export and import. Normal NodeJS just supports CommonJS module.

How to spyOn an exported standalone function using javascript jest?

It is a very simple scenario but I've struggled to find an answer for it.
helpers.ts:
export function foo() {
bar();
}
export function bar() {
// do something
}
helpers.spec.ts:
import { foo, bar } from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = // how can i set this up?
foo();
expect(barSpy).toHaveBeenCalled();
});
});
I can't do const spy = jest.spyOn(baz, 'bar'); because I don't have a module/class to put in place of "baz". It is just an exported function.
Edit:
Jest mock inner function has been suggested as a duplicate but unfortunately it doesn't help with my scenario.
Solutions in that question:
Move to separate module: I cannot do this for my scenario. If I am testing every function in my application, this would result in me creating 10s of new files which is not ideal. (To clarify, I think this solution would work but I cannot use it for my scenario. I am already mocking a separate file function successfully in this test file.)
Import the module into itself:
helpers.spec.ts:
import * as helpers from "./helpers";
describe("tests", () => {
it("example test", () => {
const barSpy = jest.spyOn(helpers, 'bar');
foo();
expect(barSpy).toHaveBeenCalled();
});
});
results in:
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
This is the closed solution:
export function bar() {
// do something
}
export function foo() {
exports.bar(); // <-- have to change to exports.bar() instead of bar()
// or this.bar(); would also work.
}
import * as utils from './utils';
describe('tests', () => {
it('example test', () => {
const barSpy = jest.spyOn(utils, 'bar');
utils.foo();
expect(barSpy).toHaveBeenCalled();
});
});
Or take a look this duplicated question

Using a function defined inside an exports function, from another file

I have some code like this in a file helperFunctions.js:
exports helperFunctions = () => {
const functionA = async(args) => {
console.log(args);
};
const functionB = async(args) => {
functionA(myArg);
};
}
How can I call functionA and functionB from a separate file altogether, say, main.js?
I've tried:
import { helperFunctions } from './helperFunctions';
//...some code
helperFunctions.functionA('hello');
// OR
functionA('hello');
The specific error is:
TypeError: _helperFunctions.helperFunctions.functionA is not a function
and when trying the second solution, it's:
ReferenceError: functionA is not defined
I'm trying to avoid importing literally every single function I'm using (by way of exporting every single function I'm using). I'd like to do something like helperFunctions.function for the functions I need.
It really need to be a function? You could export an Object:
// helperFunctions.js
let helperFunctions = {
functionA: async (args) => {
console.log(args);
},
functionB: async (args) => {
functionA(myArg);
}
}
exports helperFunctions;

js call function via closure vs call on es6 module

I have 2 functions defined like this:
export function builder(){ ... };
export function action() { return () => builder() };
Now I am trying to write a test that mock the builder function and return {};
import * as m from 'redux/modules/mymodule';
it('call buildSolrUrl', () => {
const spy = expect.spyOn(m, "builder").andReturn({});
m.action()();
expect(spy.calls.length).toEqual(1);
});
The problem is that builder does not get mock in that case.
If I change my code for:
export function action() { return () => this.builder() };
The method is mocked but my program does not work anymore because action() return a function that is executed later and this is not resolved to the right object.
To resume: My code works because the call to builder() is done via closure.
The tests are unable to mock the function that way because the function is called via the closure.
What is the best way to deal with this?

Categories

Resources