【问题标题】:how to deal with jest mock function of a module and typescript type如何处理模块和打字稿类型的笑话模拟功能
【发布时间】:2017-12-10 00:51:23
【问题描述】:

我使用ts-jestjest 用打字稿编写我的测试文件。

我很困惑如何输入模块的模拟函数。

这是我的代码:

./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(); 

  });

});

如何输入模块m的模拟函数genName

typescript在这里给我一个错误:

错误:(8, 7) TS2540: 无法分配给“genName”,因为它是常量或只读属性。

【问题讨论】:

    标签: javascript typescript jestjs


    【解决方案1】:

    您想模拟模块,然后更改其中的导出函数。这应该替换您的导入语句。

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

    【讨论】:

    • 这不起作用,因为 genName 的范围仅限于该块,并且在整个文件中不可用
    • 我在整个代码中都在使用它,所以它确实有效。如果您需要测试是否调用了 genName(或类似的东西),您可以将 jest.fn() 分配给块外部的 mock* 变量并引用它:genName: mockGenName 然后 expect(mockGenName).toHaveBeenCalled() 或其他。跨度>
    • @trevorgk 建议的解决方案工作正常。我只想强调您可能想要更改特定测试的实现:it('returns franc', () =&gt; { m.genName.mockImplementationOnce(() =&gt; 'franc') })
    • @phillyslick 感谢您的解决方案,但在这种情况下,您如何测试功能本身?喜欢:expect(genName()).toReturnSomething...?
    【解决方案2】:
    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
    })
    

    【讨论】:

    • 第二个 mockImple 不起作用我得到 Property 'mockImplementation' does not exist on type '() => Promise'。
    【解决方案3】:

    我在嘲笑它:

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

    在我的测试中:

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

    非常适合我,没有打字错误

    【讨论】:

    • 如果能解释你的答案就太好了
    【解决方案4】:

    这就是我解决相同问题的方法,也是我现在进行所有嘲笑和监视的方法。

    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);
      })
    
    })
    
    

    使用此设置,您可以以编程方式更改不同测试的模拟实现,然后断言该函数已被调用以及它被调用的内容,同时在测试之间和所有测试之后清除模拟。

    【讨论】:

    • 我得到 TypeError: jest.spyOn(...).mockImplemetation is not a function
    • @ykonda 我修正了拼写错误
    【解决方案5】:

    我得到错误的原因是:

    模块对象 foo 的属性(import * as foo from 'foo')类似于冻结对象的属性。

    欲了解更多信息,请参阅In ES6, imports are live read-only views on exported values

    当我将import * as m from './module' 更改为import m from './module'; 时,错误消失了。

    软件包版本:

    "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",
        //...
    }
    

    【讨论】:

      【解决方案6】:

      试试这个 - https://jestjs.io/docs/mock-function-api#typescript

      简而言之,只有三种可能的策略

      1. 模拟要导入的整个模块并获取模拟函数的处理程序以对其进行操作(jest.Mock()、jest.MockedFunction)
      2. 模拟部分导入的模块并获取模拟函数的处理程序以对其进行操作(jest.Mock() with factory, jest.MockedFunction)
      3. 按原样导入模块,然后监视需要模拟的函数 (jest.spy())

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-21
        • 1970-01-01
        • 2018-12-15
        • 2020-12-19
        • 2019-09-24
        • 2020-01-07
        • 2019-02-06
        相关资源
        最近更新 更多