Home > Mobile >  Attempting to mock child method, fails if parent module imports it using object destructuring
Attempting to mock child method, fails if parent module imports it using object destructuring

Time:01-07

I was doing some basic jest unit testing in attempt to learn it more.

I have this issue I do not know how to explain

This file has the child function add

// FileB.js 

const add = (a, b) => {
  return a   b;
}

module.exports = {
  add,
};

This file has the parent function addTen

// FileA.js

const { add } = require('./FileB');

const addTen = num => {
  return add(10, num);
}

module.exports = {
  addTen,
};

this is my test file, where I am trying to either check <mockedFunction/spy>.mock.calls or do toHaveBeenCalledWith to see if the inner child method, add, is being passed in 10,10 when i call addTen(10);

This file is not used in any real env, its simply me trying to learn jest unit testing more.

// randomTest.js

const { addTen } = require('../src/FileA');
const fileB = require('../src/FileB'); 

describe('temp', () => {
  it('temp', () => {
    const addSpy = jest.spyOn(fileB, 'add');

    addTen(10);
    console.log(addSpy.mock.calls);

    expect(addSpy).toHaveBeenCalledWith(10,10)
  });
});

Now for the issue, the test fails, saying add was never called, or nothing passed in. I logged the add function within FileB

However, if I modify FileA in this way, by importing entore module instead of destructuring, the test passes and I cna log out the functions and everything and see it works

This is what works

// FileA.js

const fileB = require('./FileB');

const addTen = num => {
  return fileB.add(10, num);
}

module.exports = {
  addTen,
};

Why does this slight change work?

CodePudding user response:

When you destructured add from fileB in FileA, you created a new reference to the add function that is independent of the original add function in fileB. When you mock fileB.add, you are not mocking the add function that is being used in addTen.

On the other hand, when you do not destructure add from fileB, the addTen function is using the original add function from fileB, which is being mocked in your test. That's why the test passes when you import the entire fileB module.

To make the test work with destructuring, you can mock the add function before you destructure it in FileA, like this:

// FileA.js

jest.mock('./FileB', () => {
  return {
    add: jest.fn(() => 42),
  };
});

const { add } = require('./FileB');

const addTen = num => {
 return add(10, num);
}

module.exports = {
  addTen,
};

Alternatively, you can keep the destructuring and mock add after it has been imported, but before you call addTen in your test:

// randomTest.js  
const { addTen } = require('../src/FileA');
const { add } = require('../src/FileB');

jest.mock('../src/FileB', () => {
  return {
    add: jest.fn(() => 42),
  };
});

describe('temp', () => {
 it('temp', () => {
   addTen(10);

   expect(add).toHaveBeenCalledWith(10,10)
 });
});
  • Related