Mock a namespace and a function with same name using Jest

Viewed 6366

A library I'm using is structured as

declare namespace foo {
  function bar();
};

declare namespace foo.bar {
  function baz();
};

So the two functions I need to mock are foo.bar() and foo.bar.baz().

To mock foo.bar() I was previously using

require('foo');

jest.mock('foo', () => ({
  bar: () => mockedBar,
}));

Is there any way to mock foo.bar.baz()? I tried

jest.mock('foo.bar', () => ({
}));

But it's showing a message Cannot find module 'foo.bar' from 'functions.test.js'.

4 Answers

You can define a custom mock for your module in a __mocks__ folder in your project root (defined in jest config!). So you can create __mocks__/foo.js with mocked foo module functions and Jest automatically loads this module for test purposes. Also you can specify custom path to your mock:

jest.mock('foo', () => jest.requireActual('../some/another/folder/foo.js'));

Check a Jest manual for more info

If 'foo' is under global, you may try adding codes below in the beginning of test script. Or write them in a .js file in and import it in the first line.

Object.defineProperty(global, "foo", {
    value: {
        bar: {
            baz: ()=>{
                 return true;
               },
            },
        },
    },
});

Or simply

global["foo"] = {
    bar: {
        baz: () => {
            return true;
        },
    },
};

to mock one.

According to the docs using a dot inside of a name is fine, but I have a gut feeling against it.

I recommend you to nest the namespaces.

You can include the declaration of bar into foo

declare namespace foo {
  function bar();

  declare namespace bar {
    function baz();
  };

};

Proof of concept

foo.ts

export namespace foo {
    export function bar() { return "bar"}

    export namespace bar {
        function baz() { return "baz"}
    }
}

foo.test.ts

import {foo} from "./foo"

describe("jest-mock-namespace", () => {
    it("Should mock foo.bar to return whatever we want", () => {
        const WWW = "WHATEVER_WE_WANT";
        // @ts-ignore
        foo.bar = jest.fn().mockImplementationOnce( () => WWW);

        const result = foo.bar();

        expect(result).toStrictEqual(WWW)
    });

    it("Should mock foo.bar.baz to return whatever we want", () => {
        const WWW = "WHATEVER_WE_WANT";
        // @ts-ignore
        foo.bar.baz = jest.fn().mockImplementationOnce( () => WWW);

        // @ts-ignore
        const result = foo.bar.baz();

        expect(result).toStrictEqual(WWW)
    });
})

Even though this post is the main OP is quite old, but I will add the mostly correct way of doing this.

namespaces are nothing but raw JavaScript Function objects at the end and mocking these ends up being straightforward when you start thinking of a namespace as an object.

The following structure then:

declare namespace foo {
  function bar();
};

declare namespace foo.bar {
  function baz();
};

can be mocked using Jest as follows:

jest.mock('foo', () => {
  const bar = jest.fn().mockImplementation();
  bar.baz = jest.fn().mockImplementation();
  return {
    bar
  };
});
Related