【问题标题】:How to mock a variable in ES6 Module with jest such that the actual function runs with mocked value如何用玩笑模拟 ES6 模块中的变量,以便实际函数以模拟值运行
【发布时间】:2021-06-29 13:45:17
【问题描述】:

这是一个示例代码,我想在其中测试功能 buttonReducer。 但是 reducer 函数中的 case 名称是在另一个函数中生成的。 所以,当我想单独测试我的 reducer 时,我想覆盖 RESET_TYPE、FETCH_TYPE 和 SHOW_TYPE,以便能够测试所有场景。

//main reducer.js
import {getActionTypeName} from './functions';

export const RESET_TYPE = getActionTypeName('RESET');
export const FETCH_TYPE = getActionTypeName('RESET');
export const SHOW_TYPE = getActionTypeName('RESET');

const initialState = {
  name: 'John'
};

export const buttonReducer = (state = {...initialState}, action){
  switch(action.type){
    case RESET_TYPE: {
      const newState = {"some random change", ...initialState};
      return newState;
    }
    case FETCH_TYPE: {
      const newState = {"some random change", ...initialState};
      return newState;
    }
    case SHOW_TYPE: {
      const newState = {"some random change", ...initialState};
      return newState;
    }
    default: {
      return state;
    }
  }
}

以下是我尝试过的几件事:

1.

jest.mock('./functions', ()=> {
    return {
        getActionTypeName: ()=>('return whatever I want')
    }
}

但这不起作用。

  1. 我完全了解使用 redux-mock-store 运行整个应用程序。但我特别需要的是覆盖现有变量,以便我可以对函数进行场景测试

所以本质上,我想通过更改变量的值来运行 reducer,而不仅仅是为了测试用例模拟它们。

【问题讨论】:

  • 为什么不通过不同动作类型的动作呢?这样就可以测试reducer函数的每一个代码分支
  • @slideshowp2,我愿意,但案例标识符接收未定义,因为它们是变量。它们需要在运行时解决。

标签: reactjs unit-testing jestjs mocking


【解决方案1】:

由于动作类型RESET_TYPEFETCH_TYPESHOW_TYPE是在运行时在模块范围内定义和计算的,为了消除模块import的缓存效应,需要jest.resetModules()方法。在执行测试用例之前,我们需要调用它。这样我们就可以得到一个带有新模块变量的新模块。这可以防止测试用例相互影响。

现在,我们可以使用jest.doMock(moduleName, factory, options)mockFn.mockReturnValueOnce(value) 方法来模拟./functions 模块和getActionTypeName 函数,并为每个测试用例提供不同的返回值。

例如

reducer.js:

import { getActionTypeName } from './functions';

export const RESET_TYPE = getActionTypeName('RESET');
export const FETCH_TYPE = getActionTypeName('RESET');
export const SHOW_TYPE = getActionTypeName('RESET');

const initialState = {
  name: 'John',
};

export const buttonReducer = (state = { ...initialState }, action) => {
  switch (action.type) {
    case RESET_TYPE: {
      const newState = { a: 'a', ...initialState };
      return newState;
    }
    case FETCH_TYPE: {
      const newState = { b: 'b', ...initialState };
      return newState;
    }
    case SHOW_TYPE: {
      const newState = { c: 'c', ...initialState };
      return newState;
    }
    default: {
      return state;
    }
  }
};

functions.js:

export function getActionTypeName() {
  console.log('real implementation');
}

reducer.test.js:

describe('68179950', () => {
  beforeEach(() => {
    jest.resetModules();
  });
  it('should return dynamic RESET_TYPE', () => {
    jest.doMock('./functions', () => ({
      getActionTypeName: jest.fn().mockReturnValueOnce('RUNTIME_RESET_TYPE'),
    }));
    const { buttonReducer } = require('./reducer');
    const actual = buttonReducer({}, { type: 'RUNTIME_RESET_TYPE' });
    expect(actual).toEqual({ name: 'John', a: 'a' });
  });

  it('should return dynamic FETCH_TYPE', () => {
    jest.doMock('./functions', () => ({
      getActionTypeName: jest.fn().mockReturnValueOnce('RUNTIME_RESET_TYPE').mockReturnValueOnce('RUNTIME_FETCH_TYPE'),
    }));
    const { buttonReducer } = require('./reducer');
    const actual = buttonReducer({}, { type: 'RUNTIME_FETCH_TYPE' });
    expect(actual).toEqual({ name: 'John', b: 'b' });
  });

  it('should return dynamic SHOW_TYPE', () => {
    jest.doMock('./functions', () => ({
      getActionTypeName: jest
        .fn()
        .mockReturnValueOnce('RUNTIME_RESET_TYPE')
        .mockReturnValueOnce('RUNTIME_FETCH_TYPE')
        .mockReturnValueOnce('RUNTIME_SHOW_TYPE'),
    }));
    const { buttonReducer } = require('./reducer');
    const actual = buttonReducer({}, { type: 'RUNTIME_SHOW_TYPE' });
    expect(actual).toEqual({ name: 'John', c: 'c' });
  });
});

单元测试结果:

 PASS  examples/68179950/reducer.test.js (18.013 s)
  68179950
    ✓ should return dynamic RESET_TYPE (12582 ms)
    ✓ should return dynamic FETCH_TYPE (1 ms)
    ✓ should return dynamic SHOW_TYPE (7 ms)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |   93.33 |       60 |     100 |   92.86 |                   
 reducer.js |   93.33 |       60 |     100 |   92.86 | 26                
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        22.095 s

【讨论】:

  • 哇!看起来很有希望。一定会试试这个。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-25
  • 2020-03-05
  • 1970-01-01
  • 2020-11-17
相关资源
最近更新 更多