由于动作类型RESET_TYPE、FETCH_TYPE和SHOW_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