最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - how to deal with jest mock function of a module and typescript type - Stack Overflow

programmeradmin1浏览0评论

I use ts-jest and jest to write my testing files with typescript.

I am confused how to typing the mock function of a module.

Here is my code:

./module.ts:

import {IObj} from '../interfaces';

const obj: IObj = {
  getMessage() {
    return `Her name is ${this.genName()}, age is ${this.getAge()}`;
  },

  genName() {
    return 'novaline';
  },

  getAge() {
    return 26;
  }
};

export default obj;

./module.test.ts:

import * as m from './module';

describe('mock function test suites', () => {

  it('t-1', () => {
    // I think the jest.Mock<string> type here is not correct.
    m.genName: jest.Mock<string> = jest.fn(() => 'emilie'); 
    expect(jest.isMockFunction(m.genName)).toBeTruthy();
    expect(m.genName()).toBe('emilie');
    expect(m.getMessage()).toEqual('Her name is emilie, age is 26');
    expect(m.genName).toHaveBeenCalled(); 

  });

});

how to type the mock function genName of module m?

typescript give me an error here:

Error:(8, 7) TS2540:Cannot assign to 'genName' because it is a constant or a read-only property.

I use ts-jest and jest to write my testing files with typescript.

I am confused how to typing the mock function of a module.

Here is my code:

./module.ts:

import {IObj} from '../interfaces';

const obj: IObj = {
  getMessage() {
    return `Her name is ${this.genName()}, age is ${this.getAge()}`;
  },

  genName() {
    return 'novaline';
  },

  getAge() {
    return 26;
  }
};

export default obj;

./module.test.ts:

import * as m from './module';

describe('mock function test suites', () => {

  it('t-1', () => {
    // I think the jest.Mock<string> type here is not correct.
    m.genName: jest.Mock<string> = jest.fn(() => 'emilie'); 
    expect(jest.isMockFunction(m.genName)).toBeTruthy();
    expect(m.genName()).toBe('emilie');
    expect(m.getMessage()).toEqual('Her name is emilie, age is 26');
    expect(m.genName).toHaveBeenCalled(); 

  });

});

how to type the mock function genName of module m?

typescript give me an error here:

Error:(8, 7) TS2540:Cannot assign to 'genName' because it is a constant or a read-only property.

Share Improve this question edited Dec 6, 2018 at 4:27 Lin Du asked Jul 6, 2017 at 6:52 Lin DuLin Du 102k134 gold badges332 silver badges561 bronze badges
Add a comment  | 

6 Answers 6

Reset to default 19

This is how I have solved the same problem and how I do all of my mocking and spying now.

import * as m from './module';

describe('your test', () => {
  let mockGenName;

  beforeEach(() => {
    mockGenName = jest.spyOn(m, 
      'genName').mockImplemetation(() => 'franc');
  })

  afterEach(() => {
    mockGenName.mockRestore();
  })


  test('your test description', () => {
    // do something that calls the genName function
    expect(mockGenName).toHaveBeenCalledTimes(1);
  })

})

With this setup, you can programmatically change the implementation of the mock for different tests, and then assert that the function was called and what it was called with, all while clearing your mock in between tests and after all tests.

Try this one - https://jestjs.io/docs/mock-function-api#typescript

In short there are only three strategies possible

  1. Mock the entire module being imported and get handler to the mocked function to manipulate it (jest.Mock(), jest.MockedFunction)
  2. Mock the module partially being imported and get handler to the mocked function to manipulate it (jest.Mock() with factory, jest.MockedFunction)
  3. Import the module as is and then spy on the function which needs to be mocked (jest.spy())

You want to mock the module and then alter the exported function within it. This should replace your import statement.

jest.mock('./module', () => ({
    genName: jest.fn().mockImplementation(() => 'emilie')
}))

The reason why I got the error is:

The properties of a module object foo (import * as foo from 'foo') are like the properties of a frozen object.

For more info, see In ES6, imports are live read-only views on exported values

When I changed import * as m from './module' to import m from './module';, The error is gone.

Package versions:

"typescript": "^3.6.4"
"ts-jest": "^24.1.0"
"jest": "^24.9.0",

jest.config.js:

module.exports = {
  preset: 'ts-jest/presets/js-with-ts',
  //...
}

tsconfig.json:

"compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    //...
}
import * as m from './module'

jest.mock('./module', () => ({
    genName: jest.fn().mockImplementation(() => 'emilie')
    // will return "enilie" for all tests
}))

it('returns franc', () => {
  m.genName.mockImplementationOnce(() => 'franc')
  // will return "franc" for this particular test
})

I'm mocking it a follow :

jest.mock('./module')
const {genName} = require('./module')

and in my test :

 genName.mockImplementationOnce(() => 'franc')

works great for me and no typescript errors

发布评论

评论列表(0)

  1. 暂无评论