8

I believe something fundamentally wrong in my understanding for Javascript.

In file abc.js, I have code

export function returnBoolean() {
  return true;
}

export function output() {
  return returnBoolean();
}

In the test, I do

import * as abc from "../abc";

it("test", () => {
  abc.returnBoolean = jest.fn();
  abc.returnBoolean.mockReturnValue(false);
  expect(abc.returnBoolean()).toBe(false); // This is success
  expect(abc.output()).toBe(false); // This failed because return is true
});

I don't know why abc.output() return is true.

I am really confused. Any thought is really appreciated. Thanks!

Brian Adams
  • 43,011
  • 9
  • 113
  • 111
KunYu Tsai
  • 632
  • 1
  • 10
  • 15

2 Answers2

5

output() and returnBoolean() are both in the same file and output() calls returnBoolean() directly.

Mocking the module export for returnBoolean() doesn't have any effect on output() since it is not using the module, it is calling returnBoolean() directly.

Like felixmosh said, moving returnBoolean() to a different module is one way to be able to mock the call to returnBoolean() within output().

The other way is to simply import the module back into itself and use the module to call returnBoolean() within output() like this:

// import the module back into itself
import * as abc from './abc';

export function returnBoolean() {
  return true;
}

export function output() {
  return abc.returnBoolean(); // use the module to call returnBoolean()
}

With this approach your unit test should work.

Brian Adams
  • 43,011
  • 9
  • 113
  • 111
4

Think about it, whenever you import abc module, all the function inside that module are declared, therefore, output function get "bounded" to the original returnBoolean.

Your mock won't apply on the original function.

You have 2 choices:

  1. If the returnBoolean can be on a separate module, you will able to use jest's mocking mechnisem.
  2. If you able to change the interface of output method so it will be able to get the returnBoolean from outside of the module. Then you will be able to pass to it, jest.fn() and make your expectation on it.
felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • **whenever you import abc module, all the function inside that module are declared, therefore, output function get "bounded" to the original returnBoolean.** Thanks for the precious hint. However, by any chance you could give me more explanation for that sentence? I can't quite understand it. – KunYu Tsai Aug 17 '18 at 18:30
  • 1
    Think of that as when you require file, the process behind the scene stops, read the file, load it into memory and executes it. Whenever it executed, the way you wrote the function out, it uses the “pointer” to the fonction from the module. – felixmosh Aug 17 '18 at 23:00
  • 1
    Therefore, if later on you are trying to change that pointer, you won’t affect pointer that “out” function burned in it self. Hope it makes that more clear. – felixmosh Aug 17 '18 at 23:04