Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mock an ES6 module import using Jest?

I want to test that one of my ES6 modules calls another ES6 module in a particular way. With Jasmine this is super easy --

The application code:

// myModule.js import dependency from './dependency';  export default (x) => {   dependency.doSomething(x * 2); } 

And the test code:

//myModule-test.js import myModule from '../myModule'; import dependency from '../dependency';  describe('myModule', () => {   it('calls the dependency with double the input', () => {     spyOn(dependency, 'doSomething');      myModule(2);      expect(dependency.doSomething).toHaveBeenCalledWith(4);   }); }); 

What's the equivalent with Jest? I feel like this is such a simple thing to want to do, but I've been tearing my hair out trying to figure it out.

The closest I've come is by replacing the imports with requires, and moving them inside the tests/functions. Neither of which are things I want to do.

// myModule.js export default (x) => {   const dependency = require('./dependency'); // Yuck   dependency.doSomething(x * 2); }  //myModule-test.js describe('myModule', () => {   it('calls the dependency with double the input', () => {     jest.mock('../dependency');      myModule(2);      const dependency = require('../dependency'); // Also yuck     expect(dependency.doSomething).toBeCalledWith(4);   }); }); 

For bonus points, I'd love to make the whole thing work when the function inside dependency.js is a default export. However, I know that spying on default exports doesn't work in Jasmine (or at least I could never get it to work), so I'm not holding out hope that it's possible in Jest either.

like image 210
Cam Jackson Avatar asked Nov 07 '16 12:11

Cam Jackson


People also ask

How do you mock an import in Jest?

To mock an imported function with Jest we use the jest. mock() function. jest. mock() is called with one required argument - the import path of the module we're mocking.

How do you mock a module using Jest?

unmock('moduleName') in tests that should use the actual module implementation. Note: In order to mock properly, Jest needs jest. mock('moduleName') to be in the same scope as the require/import statement. Here's a contrived example where we have a module that provides a summary of all the files in a given directory.

Does Jest support ES6 modules?

Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package. json .

Can I use ES6 imports?

Importing can be done in various ways:Node js doesn't support ES6 import directly. If we try to use import for importing modules directly in node js it will throw out the error.


1 Answers

Edit: Several years have passed and this isn't really the right way to do this any more (and probably never was, my bad).

Mutating an imported module is nasty and can lead to side effects like tests that pass or fail depending on execution order.

I'm leaving this answer in its original form for historical purposes, but you should really use jest.spyOn or jest.mock. Refer to the jest docs or the other answers on this page for details.

Original answer follows:


I've been able to solve this by using a hack involving import *. It even works for both named and default exports!

For a named export:

// dependency.js export const doSomething = (y) => console.log(y) 
// myModule.js import { doSomething } from './dependency';  export default (x) => {   doSomething(x * 2); } 
// myModule-test.js import myModule from '../myModule'; import * as dependency from '../dependency';  describe('myModule', () => {   it('calls the dependency with double the input', () => {     dependency.doSomething = jest.fn(); // Mutate the named export      myModule(2);      expect(dependency.doSomething).toBeCalledWith(4);   }); }); 

Or for a default export:

// dependency.js export default (y) => console.log(y) 
// myModule.js import dependency from './dependency'; // Note lack of curlies  export default (x) => {   dependency(x * 2); } 
// myModule-test.js import myModule from '../myModule'; import * as dependency from '../dependency';  describe('myModule', () => {   it('calls the dependency with double the input', () => {     dependency.default = jest.fn(); // Mutate the default export      myModule(2);      expect(dependency.default).toBeCalledWith(4); // Assert against the default   }); });  
like image 152
Cam Jackson Avatar answered Sep 27 '22 19:09

Cam Jackson