Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jest mock inner function

I have one file called helper.js that consist of two functions

export const funcA = (key) => {    return funcB(key) };  export const funcB = (key,prop) => {    return someObj; }; 

I have my helper.spec.js to test the helper.js file functions.

import {funcA,funcB} from 'helper';  describe('helper', () => {    test('testFuncB', () => {     }    test('testFuncA', () => {     } } 

The test for funcB is pretty simple i just call it and expect someObj
The problem is to test funcA, in order to test it i want to mock the response of funcB.

I want testFuncB call the actual funcB and testFuncA call mocked funcB

How can i achieve funcB to be mocked and original in my two tests?

This is not a duplicate. It is a different case: they mock inner called functions only, if I remove the testFuncB then it will be the same but I must perform test on testFuncB too.

like image 839
Alexander Gorelik Avatar asked Jul 10 '18 15:07

Alexander Gorelik


People also ask

How do you mock a function inside a function using Jest?

To mock inner function with Jest and JavaScript, we should export the inner function in a module. import * as funcBModule from "./funcB"; import { funcA } from "./foo"; describe("helper", () => { test("test funcB", () => { expect(funcBModule. funcB()). toBe("original"); }); test("test funcA", () => { const spy = jest.

Can I use Jest mock inside a test?

mock() doesn't work inside tests, only outside tests. Bookmark this question.

How do you mock a function in class Jest?

In order to mock a constructor function, the module factory must return a constructor function. In other words, the module factory must be a function that returns a function - a higher-order function (HOF). Since calls to jest. mock() are hoisted to the top of the file, Jest prevents access to out-of-scope variables.

How do you mock functions in the same module using Jest?

You can create a namespace that you export as the default object and call b using the namespace. This way, when you call jest. mock it will replace the b function on the namespace object. const f = require('./f'); jest.


1 Answers

If an ES6 module directly exports two functions (not within a class, object, etc., just directly exports the functions like in the question) and one directly calls the other, then that call cannot be mocked.

In this case, funcB cannot be mocked within funcA the way the code is currently written.

A mock replaces the module export for funcB, but funcA doesn't call the module export for funcB, it just calls funcB directly.


Mocking funcB within funcA requires that funcA call the module export for funcB.

That can be done in one of two ways:


Move funcB to its own module

funcB.js

export const funcB = () => {   return 'original'; }; 

helper.js

import { funcB } from './funcB';  export const funcA = () => {   return funcB(); }; 

helper.spec.js

import * as funcBModule from './funcB'; import { funcA } from './helper';  describe('helper', () => {    test('test funcB', () => {     expect(funcBModule.funcB()).toBe('original');  // Success!   });    test('test funcA', () => {     const spy = jest.spyOn(funcBModule, 'funcB');     spy.mockReturnValue('mocked');      expect(funcA()).toBe('mocked');  // Success!      spy.mockRestore();   }); }); 

Import the module into itself

"ES6 modules support cyclic dependencies automatically" so it is perfectly valid to import a module into itself so that functions within the module can call the module export for other functions in the module:

helper.js

import * as helper from './helper';  export const funcA = () => {   return helper.funcB(); };  export const funcB = () => {   return 'original'; }; 

helper.spec.js

import * as helper from './helper';  describe('helper', () => {    test('test funcB', () => {     expect(helper.funcB()).toBe('original');  // Success!   });    test('test funcA', () => {     const spy = jest.spyOn(helper, 'funcB');     spy.mockReturnValue('mocked');      expect(helper.funcA()).toBe('mocked');  // Success!      spy.mockRestore();   }); }); 
like image 87
Brian Adams Avatar answered Sep 22 '22 22:09

Brian Adams