我试图在导入的React模块中仅模拟一个功能,保持模块其余部分不变,并在所有测试中都做到这一点。
我正在使用带有一个测试的全新create-react-app项目来观察问题。
复制步骤:
create-react-app test
src/App.test.js
作为唯一的测试文件npm run test
App.test.js
jest.mock('react', () => {
jest.dontMock('react');
const React = require('react');
const lazy = jest.fn();
return {
...React,
lazy
};
});
import * as React from 'react';
const React2 = require('react');
it('should partially mock React module', async () => {
expect(jest.isMockFunction(React.lazy)).toBe(true); // passes
expect(jest.isMockFunction(React2.lazy)).toBe(true); // fails
expect(jest.isMockFunction(require('react').lazy)).toBe(true); // fails
expect(jest.isMockFunction((await import('react')).lazy)).toBe(true); // fails
});
这里的问题似乎是jest.dontMock
,因为它阻止了require
和动态import
的模仿,但仍不清楚为什么可以模拟静态import
,因为它以任何方式使用require
。这是转档文件:
"use strict";
jest.mock('react', () => {
jest.dontMock('react');
const React = require('react');
const lazy = jest.fn();
return (0, _objectSpread2.default)({}, React, {
lazy
});
});
var _interopRequireWildcard3 = require("...\\node_modules\\@babel\\runtime/helpers/interopRequireWildcard");
var _interopRequireDefault = require("...\\node_modules\\@babel\\runtime/helpers/interopRequireDefault");
var _interopRequireWildcard2 = _interopRequireDefault(require("...\\node_modules\\@babel\\runtime/helpers/interopRequireWildcard"));
var _objectSpread2 = _interopRequireDefault(require("...\\node_modules\\@babel\\runtime/helpers/objectSpread"));
var React = _interopRequireWildcard3(require("react"));
const React2 = require('react');
...
这可能与create-react-app Jest + Babel设置有关,因为我无法使jest.dontMock
在Vanilla Jest和require
上无法正常工作。
为什么静态React
会被模拟,而React2
和其余的不是?里面到底发生了什么?
如何解决jest.dontMock
当前行为,以便在顶层局部模拟模块?
答案 0 :(得分:1)
一种简单的解决方案是在React.lazy
中模拟setupTest.js
:
import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
jest.spyOn(React.lazy);
对于每个测试文件,require/imports
中的任何后续react
都会被部分模拟。
工作示例:https://github.com/mattcarlotta/react-lazy-mocked(我不使用create-react-app
,但是可以像我一样使用jest
进行设置)< / p>
安装:
git clone git@github.com:mattcarlotta/react-lazy-mocked.git
cd react-lazy-mocked
yarn install
yarn test
root / __ tests __ / root.test.js
import React from 'react';
import App from '../index.js';
const React2 = require('react');
describe('App', () => {
const wrapper = mount(<App />);
it('renders without errors', () => {
const homeComponent = wrapper.find('.app');
expect(homeComponent).toHaveLength(1);
});
it('should partially mock React module', async () => {
expect(jest.isMockFunction(await require('react').lazy)).toBe(true); // eslint-disable-line global-require
expect(jest.isMockFunction(React)).toBe(false);
expect(jest.isMockFunction(React.lazy)).toBe(true);
expect(jest.isMockFunction(React2)).toBe(false);
expect(jest.isMockFunction(React2.lazy)).toBe(true);
});
it('should no longer be partially mocked within the test file', () => {
React.lazy.mockRestore();
expect(jest.isMockFunction(React.lazy)).toBe(false);
});
});
页面/首页/ __测试__ / Home.test.js
import React from 'react';
import Home from '../index.js';
describe('Home', () => {
const wrapper = shallow(<Home />);
it('renders without errors', () => {
const homeComponent = wrapper.find('.app');
expect(homeComponent).toHaveLength(1);
});
it('should partially mock React module', async () => {
expect(jest.isMockFunction(React.lazy)).toBe(true);
});
});
工作示例:https://github.com/mattcarlotta/named-react-lazy-mocked
安装:
git clone git@github.com:mattcarlotta/named-react-lazy-mocked.git
cd named-react-lazy-mocked
yarn install
yarn test
实用程序/ __ mocks __ / react.js
jest.mock('react', () => ({
...require.requireActual('react'),
lazy: jest.fn(),
}));
module.exports = require.requireMock('react');
utils / setup / setupTest.js (可选,您可以将模拟的react
文件添加为global
开玩笑的函数,这样就不必编写{{ 1}}(每次测试):
import * as React from 'react'
root / __ tests __ / root.test.js
import { JSDOM } from 'jsdom';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
// import React from '../__mocks__/react';
configure({ adapter: new Adapter() });
// global.React = React;