2

It is a very simple scenario but I've struggled to find an answer for it.

helpers.ts:

export function foo() {
    bar();
}

export function bar() {
    // do something
}

helpers.spec.ts:

import { foo, bar } from "./helpers";

describe("tests", () => {
    it("example test", () => {
        const barSpy = // how can i set this up?
        foo();
        expect(barSpy).toHaveBeenCalled();
    });
});

I can't do const spy = jest.spyOn(baz, 'bar'); because I don't have a module/class to put in place of "baz". It is just an exported function.

Edit: Jest mock inner function has been suggested as a duplicate but unfortunately it doesn't help with my scenario.

Solutions in that question:

  • Move to separate module: I cannot do this for my scenario. If I am testing every function in my application, this would result in me creating 10s of new files which is not ideal. (To clarify, I think this solution would work but I cannot use it for my scenario. I am already mocking a separate file function successfully in this test file.)

  • Import the module into itself:

helpers.spec.ts:

import * as helpers from "./helpers";

describe("tests", () => {
    it("example test", () => {
        const barSpy = jest.spyOn(helpers, 'bar');
        foo();
        expect(barSpy).toHaveBeenCalled();
    });
});

results in:

expect(jest.fn()).toHaveBeenCalled()

Expected number of calls: >= 1
Received number of calls:    0
Kemal Tezer Dilsiz
  • 3,739
  • 5
  • 24
  • 43
  • Does this answer your question? [Jest mock inner function](https://stackoverflow.com/questions/51269431/jest-mock-inner-function) – buzatto Jan 07 '21 at 04:47
  • Unfortunately that doesn't answer my question. Mocking in that scenario works within the spec.ts file but not in the original file. The original file still calls the actual bar() rather than the mocked bar() – Kemal Tezer Dilsiz Jan 07 '21 at 16:02

1 Answers1

4

This is the closed solution:

export function bar() {
  // do something
}

export function foo() {
  exports.bar();   // <-- have to change to exports.bar() instead of bar()
  // or this.bar(); would also work.
}

import * as utils from './utils';

describe('tests', () => {
  it('example test', () => {
    const barSpy = jest.spyOn(utils, 'bar');
    utils.foo();
    expect(barSpy).toHaveBeenCalled();
  });
});

Or take a look this duplicated question

Kemal Tezer Dilsiz
  • 3,739
  • 5
  • 24
  • 43
Ron
  • 6,037
  • 4
  • 33
  • 52
  • 2
    `exports.bar()` relies on the fact that ES module is transpiled to CommonJS, which is a mistake in general. – Estus Flask Jan 07 '21 at 08:47
  • Unfortunately, I cannot use exports.bar() in my scenario. But that does indeed work! I'll check with my team to see whether we can use exports in our scenario. – Kemal Tezer Dilsiz Jan 07 '21 at 16:02
  • 1
    I've found about that this.bar() also works. I could definitely use this (which i realize would be same as using exports). I'll accept this as the answer but do a small edit to mention this works as well. – Kemal Tezer Dilsiz Jan 07 '21 at 16:13