3

Suppose we have a file(source.js) to test:

// source.js
import x from './x';

export default () => x();

And the unit test code is very simple:

// test.js
import test from 'ava';
import source from './source'

test("OK", t => {
  source();
  t.pass();
});

But this is the tricky thing. The file "./x" does not exist in the test environment. Since it is a unit test, we do not need "./x". We can mock the function "x()" anyhow(using sinon or something else). But the unit test tool, ava, keeps showing "Error: Cannot find module './x'";

Is there any way to run the unit test without the file "./x"?

Jim Jin
  • 1,249
  • 1
  • 15
  • 28

3 Answers3

1

To do this, you'd need to override the import process itself. There are libraries for doing something similar-- overriding the require function with proxyquire, for example-- but these force you to invoke their custom function to import the module under test. In other words, you'd need to abandon using ES6 module syntax to use them.

You should also note that ES modules are only supported experimentally (and relatively recently) in Node. If you're transpiling with Babel, you're not actually using ES modules. You're using the syntax, sure, but Babel transpiles them to CommonJS "equivalents", complete with require calls and module.exports assignments.

As such, if you're using Babel, you can probably proxyquire to import modules under test in your test files, even if you're using ES module syntax in those modules. This will break, though, if you ever switch away from Babel. :\

My personal recommendation would be to avoid directly exporting anything you might need to stub. So functions like x should be in a static module imported like import foo from './foo' and invoked like foo.x(). Then, you can easily stub it with sinon.stub(foo, 'x'). Of course, the './foo' file will have to exist for this still, but what it really comes down to is how hardcore you want to be about TDD practices versus how much complexity you're willing to introduce to your mocking/stubbing process. I prefer relaxing the former to avoid the latter, but in the end it's up to you.

sripberger
  • 1,682
  • 1
  • 10
  • 21
  • Thanks for answering. – Jim Jin May 25 '18 at 14:45
  • Thanks for answering. I'm using the latest node.js with the '--experimental-modules' feature. I'm OK with the experimental one since I can escape from a lot of extra work by getting rid of bable. So, all of my source code files are *.mjs. However, AVA does not support mjs well. And the bable plug-in it's used can't generate the correct code. It's leads to some grammar errors during the test while the same code works in the product environment. – Jim Jin May 25 '18 at 14:53
  • And let me change my question slightly. We have x.mjs and source.mjs. And x.mjs does exist but there would be some error to give it to bable(I don't know why and don't want to investigate). Is it possible to let test.js(or test.mjs) run without changing the code above? – Jim Jin May 25 '18 at 14:59
  • I can almost guarantee that the reason it's not working with Babel is the `.mjs` extension. As for your new question, I don't know anything about AVA, but your import syntax is fine as long as 'x.mjs` or 'x.js' exists. Whether or not your test passes, however, will depend on whether or not that file exports a function, of course – sripberger May 29 '18 at 13:53
1

If you are using Jest, it can be achieved easily by mocking the import using the inbuilt mock method of jest. Please refer the link below to find more about ES6 import mocks

https://jestjs.io/docs/en/es6-class-mocks

Sarath P S
  • 131
  • 5
  • 1
    This is about ES6 classes, not modules. Also a general solution independent of the test runner would be nice. – Lux Dec 03 '19 at 23:39
  • 1
    It's worth noting that jest doesn't currently support native ES6 modules. If you're using Jest for your testing, you're almost certainly using babel transpiled modules instead. – chaorace Jun 02 '20 at 18:11
0

If you are using jest with JavaScript this is very simple:

use jest.mock('MODULE_NAME')

If it is a node module or your own module, no problem jest will automatically mock that module.

tomerpacific
  • 4,704
  • 13
  • 34
  • 52
Vivek Anand
  • 1,264
  • 8
  • 15