我对在Jest中嘲笑如何对实现进行单元测试感到困惑。问题是我想模仿不同的预期行为。
有没有办法实现这个目标?因为导入只能在文件的顶部,并且能够模拟在导入之前必须声明的内容。我也尝试传递一个本地函数,所以我可以覆盖这个行为,但是jest抱怨你不允许传递任何本地函数。
jest.mock('the-package-to-mock', () => ({
methodToMock: jest.fn(() => console.log('Hello'))
}));
import * as theThingToTest from '../../../app/actions/toTest'
import * as types from '../../../app/actions/types'
it('test1', () => {
expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})
it('test2', () => {
//the-package-to-mock.methodToMock should behave like something else
expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})
在内部,您可以想象theThingToTest.someAction()
使用the-package-to-mock.methodToMock
答案 0 :(得分:41)
您可以使用间谍进行模拟并导入模拟模块。在测试中,您可以使用mockImplementation
设置模拟的行为方式:
jest.mock('the-package-to-mock', () => ({
methodToMock: jest.fn()
}));
import {methodToMock} from 'the-package-to-mock'
it('test1', () => {
methodToMock.mockImplementation(() => 'someValue')
})
it('test2', () => {
methodToMock.mockImplementation(() => 'anotherValue')
})
答案 1 :(得分:3)
另一种方法是使用 jest.doMock(moduleName, factory, options)。
例如
the-package-to-mock.ts
:
export function methodToMock() {
return 'real type';
}
toTest.ts
:
import { methodToMock } from './the-package-to-mock';
export function someAction() {
return {
type: methodToMock(),
};
}
toTest.spec.ts
:
describe('45006254', () => {
beforeEach(() => {
jest.resetModules();
});
it('test1', () => {
jest.doMock('./the-package-to-mock', () => ({
methodToMock: jest.fn(() => 'type A'),
}));
const theThingToTest = require('./toTest');
expect(theThingToTest.someAction().type).toBe('type A');
});
it('test2', () => {
jest.doMock('./the-package-to-mock', () => ({
methodToMock: jest.fn(() => 'type B'),
}));
const theThingToTest = require('./toTest');
expect(theThingToTest.someAction().type).toBe('type B');
});
});
单元测试结果:
PASS examples/45006254/toTest.spec.ts
45006254
✓ test1 (2016 ms)
✓ test2 (1 ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
toTest.ts | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 3.443 s
源代码:https://github.com/mrdulin/jest-v26-codelab/tree/main/examples/45006254
答案 2 :(得分:0)
CTRL + BREAK
最适合我们。查看以前的答案:
答案 3 :(得分:0)
我使用以下模式:
'use strict'
const packageToMock = require('../path')
jest.mock('../path')
jest.mock('../../../../../../lib/dmp.db')
beforeEach(() => {
packageToMock.methodToMock.mockReset()
})
describe('test suite', () => {
test('test1', () => {
packageToMock.methodToMock.mockResolvedValue('some value')
expect(theThingToTest.someAction().type).toBe(types.SOME_TYPE)
})
test('test2', () => {
packageToMock.methodToMock.mockResolvedValue('another value')
expect(theThingToTest.someAction().type).toBe(types.OTHER_TYPE)
})
})
说明:
您要在测试套件级别上模拟要使用的类,请确保在每次测试之前重置模拟,并且对于每个测试,您都要使用mockResolveValue描述返回模拟时将返回的内容
答案 4 :(得分:0)
Andreas答案可以很好地与函数配合使用,这是我使用它的结果:
// You don't need to put import line after the mock.
import {supportWebGL2} from '../utils/supportWebGL';
// functions inside will be auto-mocked
jest.mock('../utils/supportWebGL');
const mocked_supportWebGL2 = supportWebGL2 as jest.MockedFunction<typeof supportWebGL2>;
// Make sure it return to default between tests.
beforeEach(() => {
// set the default
supportWebGL2.mockImplementation(() => true);
});
it('display help message if no webGL2 support', () => {
// only for one test
supportWebGL2.mockImplementation(() => false);
// ...
});
如果您的模拟模块不是函数,它将无法正常工作。我无法仅通过一个测试就更改导出的布尔值的模拟:/。我的建议是,重构为函数,或者制作另一个测试文件。
export const supportWebGL2 = /* () => */ !!window.WebGL2RenderingContext;
// This would give you: TypeError: mockImplementation is not a function