简体   繁体   中英

jest.mock (intermediate value)… is not a function

I have the following code I want to test:

export class MetricBuilder {
  metricDimensions: MetricDimensionsType;
  metricName: MetricName;
  metricValue: number;

  constructor() {
    this.metricDimensions = [];
    this.metricName = '';
  }

  public withReferenceId = (referenceId: string) => {
    this.addDimension(MetricDimensions.ReferenceId, referenceId);
    return this;
  }
};

My test file looks like this:

jest.mock('../../app/metrics/MetricBuilder');

import { MetricBuilder } from "../../app/metrics/MetricBuilder";

import Mock = jest.Mock;

let MetricBuilderMock: Mock;

describe('blah', () => {
  beforeEach(() => {
    MetricBuilderMock = MetricBuilder as Mock;
    MetricBuilderMock.mockReset();
  });

  it.only('blah', async () => {
    const a = new MetricBuilder().withReferenceId('sldkfj');
    expect(MetricBuilderMock.mock.instances[0].withReferenceId).toHaveBeenCalledTimes(1);
  });
});

I get the following output from jest when executing the test:

  TypeError: (intermediate value).withReferenceId is not a function

      14 | 
      15 |   it.only('blah', async () => {
    > 16 |     const a = new MetricBuilder().withReferenceId('sldkfj');
         |                                   ^
      17 |     expect(MetricBuilderMock.mock.instances[0].withReferenceId).toHaveBeenCalledTimes(1);
      18 |   });
      19 | });

I can't figure out why this is happening as I thought jest would automock the constructor and all the methods of the module. Also, I am using typescript if that makes a difference here.

It turns out I didn't read the docs carefully enough. It says that:

Calling jest.mock('./sound-player') returns a useful "automatic mock" you can use to spy on calls to the class constructor and all of its methods. It replaces the ES6 class with a mock constructor, and replaces all of its methods with mock functions that always return undefined. Method calls are saved in theAutomaticMock.mock.instances[index].methodName.mock.calls.

Please note that if you use arrow functions in your classes, they will not be part of the mock. The reason for that is that arrow functions are not present on the object's prototype, they are merely properties holding a reference to a function.

So the issue in my case was that I used arrow functions in my class, and the mock was empty.

The correct version of the class looks like this:

export class MetricBuilder {
  metricDimensions: MetricDimensionsType;
  metricName: MetricName;
  metricValue: number;

  constructor() {
    this.metricDimensions = [];
    this.metricName = '';
  }

  public withReferenceId(referenceId: string) {
    this.addDimension(MetricDimensions.ReferenceId, referenceId);
    return this;
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM