Search code examples
node.jsunit-testingmockingmocha.jssinon

Mocha: Can't stub function in file that was already required in another test file


I'm using Mocha to run a test suite on fileToTest.js with requires greeting.js

// --fileToTest.js--

const { greeting } = require('./greeting');

module.exports = () => greeting();
// --greeting.js--

module.exports.greeting = () => 'hi!';

By itself, this test file successfully stubs greeting.

// --test2.js--
let parent;
const sinon = require('sinon');
const chai = require('chai');
const greeting = require('../../greeting.js');

const { expect } = chai;

describe('stubbed /hi', () => {
  before(async () => {
    sinon.stub(greeting, 'greeting').callsFake((req, res, next) => 'bye!');
    parent = require('../../parent.js');
  });

  after(async () => {
    greeting.greeting.restore();
  });
  it('should say bye', async function () {
    expect(parent()).to.be.equal('bye!');
  });
});

However if I run a test suite and have another test file that requires fileToTest.js, like test1.js below, the first test above (test2.js) won't stub greeting.

// --test1.js--
const chai = require('chai');
const fileToTest = require('../../fileToTest.js');

const { expect } = chai;

describe('not stubbed /hi', () => {
  it('should say hi', () => {
    expect(fileToTest()).to.be.equal('hi!');
  });
});

It seems once test1.js requires fileToTest, mocha doesn't reload the fileToTest on the test2.js's require. So fileToTest is stuck with the old greeting function.

Whats the proper way to stub a function in this situation?

Repo


Solution

  • This answer worked. I had to delete the cache.

      before(async () => {
        delete require.cache[require.resolve('../../fileToTest.js')]; // <------
    
        sinon.stub(greeting, 'greeting').callsFake((req, res, next) => 'bye!');
        fileToTest = require('../../fileToTest.js');
      });