GoldFlsh
GoldFlsh

Reputation: 1334

How to ignore import statements with Jest testing?

I am trying to write a test for a factory module. This factory module imports an object module that it then returns a new instance of given a specific string. The object that it imports imports more things, and one of the things it is importing imports another thing which imports another script that depends on some environment variables. That script runs, fails to find the environment variables it needs and kills the process before the test even gets started.

I don't find it should be necessary to import so many layers to test this specific factory. What's the right approach to solve this problem? Note that I'm very new to javascript/typescript, so any insight into the way package imports are supposed to work would be helpful.

jest.mock doesn't prevent the import statements on the underlying object from running.

//object-factory.ts
import {AnObject} from '../interfaces/an-object';
import VeryNiceObject from './very-nice-object';

export const VERY_NICE_STRING = 'this-string-is-very-nice'

export class ObjectFactory {
    private readonly str: string;

    constructor(str: string) {
        this.str = str;
    }

    public build(): AnObject {
        switch (this.str) {
            case VERY_NICE_STRING:
                return new VeryNiceObject();
            default:
                throw new Error(`Unknown string ${this.str}`);
        }
    }
}

I am trying to isolate this module under test. My test looks like this -

jest.mock("../very-nice-object")

import {AnObject} from "../../interfaces/an-object";
import {ObjectFactory, VERY_NICE_STRING} from "../object-factory"; //FAILS HERE
import VeryNiceObject from "../very-nice-object";

describe('object-factory', () => {
    test("build returns VeryNiceObject", () => {
        const factory = new ObjectFactory(VERY_NICE_STRING)
        const objectResult = factory.build()
        expect(objectResult instanceof VeryNiceObject)
    })
});

I have also tried running with automock on at the top of the file and it fails for a different reason.

jest.autoMockOn() 
...rest of test
  ● Test suite failed to run

    TypeError: Expected a string

      at escapeStringRegexp (node_modules/colors/lib/colors.js:80:11)
      at node_modules/colors/lib/colors.js:101:18
          at Array.forEach (<anonymous>)
      at node_modules/colors/lib/colors.js:99:27
      at Object.<anonymous> (node_modules/colors/lib/colors.js:109:3)

Upvotes: 8

Views: 10252

Answers (3)

serv-inc
serv-inc

Reputation: 38307

Just to save you the click: In https://stackoverflow.com/a/40809682/1587329, @Andrew (go upvote) recommends to use:

 jest.mock("../../src/styles.less", () => jest.fn());

Without a factory, jest tries to parse the file to find out which names to mock.

Upvotes: 15

David Pol&#225;k
David Pol&#225;k

Reputation: 1691

I just spent a fun hour trying to debug this error message.

For me the root cause was that the mock wasn't implemented in full and I had a function which used the mock in the same file as the tested function, even though it wasn't imported or used anywhere. Just parsing the file gives the error.

● Test suite failed to run

    TypeError: Expected a string

      at escapeStringRegexp (node_modules/colors/lib/colors.js:80:11)
      at node_modules/colors/lib/colors.js:101:18
          at Array.forEach (<anonymous>)
      at node_modules/colors/lib/colors.js:99:27
      at Object.<anonymous> (node_modules/colors/lib/colors.js:109:3)

Also turning off autoMock in Jest configuration might be a useful debugging step.

Upvotes: 1

GoldFlsh
GoldFlsh

Reputation: 1334

This didn't appear to be possible. What ended up having to happen was wrapping the script's behavior in an exported function. I then was able to mock that function. I did have to change any other modules relying on that script, to call the function instead after importing.

Upvotes: 1

Related Questions