neo-technoker
neo-technoker

Reputation: 389

Stubbing a nested function in Jest

I have two functions in a module at the module scope. One of the functions is used by another.

async function allCinemas({ puppeteer, states }) {
  const cinemaDetails = [];
  const page = await puppeteer
    .launch({
      handleSIGINT: true /*devtools: false,headless: true*/
    })
    .then(browser => browser.newPage());

  await page.setViewport({ width: 1366, height: 735 }); //form factor - laptop/PC
  await page.goto("https://www.somesite.come");

  for (const state of states) {
    const res = await cinemasfromState(page, state);
    res.forEach(cin => {
      cinemaDetails.push(cin);
    });
  }
  await page.close();

  return cinemaDetails;
}

async function cinemasfromState(page, state) {
  const CINEMA_SELECTOR = `div[$[STATE]] div.top-select-option h.element`;

  let res = await page.evaluate(
    (elementPath, state) => {
      let results = Array.from(document.querySelectorAll(elementPath)).map(
        function(cin, index) {
          let result = {
            cinemaState: this.state,
            cinemaId: cin.getAttribute("id"),
            cinemaName: cin.getAttribute("name"),
          };
          return result;
        },
        { state }
      );

      return  [...results.reduce((a, c) => a.set(c.cinemaId, c), new Map()).values()];     

    },
    CINEMA_SELECTOR.replace("$[STATE]", state),
    state
  );

  return  Promise.resolve(res);
}
export { allCinemas, cinemasfromState };

I have separately tested function cinemasfromState

Therefore when I test function allCinemas, I am thinking of stubbing function cinemasfromState.

How can I not stub/mock cinemasfromState so that I don’t have to duplicate testing?

Upvotes: 2

Views: 611

Answers (2)

Andreas Köberle
Andreas Köberle

Reputation: 110892

As long as both function are defined in the same module there is no sane way to mock only one function that is then used by the other function is the module. Maybe it becomes clear why if you think about the order the code is executed.

  1. Inside the module the two functions A and B are declared. Function B has reference to function A.
  2. The module is imported into your test. At this point in time there is no way to remove the reference to A inside of B.

So the only solution to test this two functions with mocking one of them is to put them in differnt modules, as you can easily mock one of them in the test. As you export both of them it should be quite easy to put them in different modules.

Upvotes: 0

Dinesh Pandiyan
Dinesh Pandiyan

Reputation: 6289

Use sinon

While testing b, you should test for its behavior on different responses from a (happy and fail flows). So you need to stub a with different returns to test b correctly.

import * as allMethods from './whereever-the-file-is';
import sinon from 'sinon';

// inside your test case
const aStub = sinon.stub(allMethods, 'a');

aStub.returns('x');
// test your function b on what it should do when a returns 'x'

aStub.returns('y');
// test your function b on what it should do when a returns 'y'

I haven't tested this code, so pl refer to official docs if you need to know more about sinon stubs.

Upvotes: 1

Related Questions