gpt4 book ai didi

javascript - 使用 Jest 部分模拟 React 模块

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:23:48 25 4
gpt4 key购买 nike

我试图在导入的 React 模块中仅模拟一个函数,保持模块的其余部分未被模拟,并在所有测试的顶层执行此操作。

我正在使用带有单个测试的新 create-react-app 项目来观察问题。

重现步骤:

  • create-react-app 测试
  • 使用提供的src/App.test.js作为唯一的测试文件
  • npm 运行测试

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 一起工作不正确。

为什么 static React import 被 mocked 但 React2 和其他的不是?里面到底发生了什么?

如何修复 jest.dontMock 当前行为以在顶层部分模拟模块?

最佳答案

默认导入:

一个简单的解决方案是在 setupTest.js 中模拟 React.lazy:

import React from 'react';
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

jest.spyOn(React.lazy);

react 的任何后续 require/imports 都将针对每个测试文件进行部分模拟。

工作示例:https://github.com/mattcarlotta/react-lazy-mocked (我不使用 create-react-app,但是 jest 可以像我一样设置)

安装:

  • git clone git@github.com:mattcarlotta/react-lazy-mocked.git
  • cd react-lazy-mocked
  • yarn 安装
  • yarn 测试

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

pages/Home/__tests__/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 安装
  • yarn 测试

utils/__mocks__/react.js

jest.mock('react', () => ({
...require.requireActual('react'),
lazy: jest.fn(),
}));
module.exports = require.requireMock('react');

utils/setup/setupTest.js(可选,您可以将模拟的 react 文件添加为 global jest 函数,这样您就不会不必为每个测试编写 import * as React from 'react':

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;

root/__tests__/root.test.js

import * as 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);
});
});

关于javascript - 使用 Jest 部分模拟 React 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55327095/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com