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 import
s with require
s, 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.
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.
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.
Jest will enable compilation from ECMAScript modules to CommonJS automatically, without having to inform additional options to your jest property inside package. json .
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.
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 }); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With