javascript - 在 React with Jest 中为 @material-ui withStyles 创建手动模拟

标签 javascript reactjs mocking jestjs material-ui

我正在尝试为 @material-ui/core/styles 创建手动模拟模块,导出名为 withStyles 的 HOC .

将内联模拟与 jest.mock 一起使用完美运行,但是当我尝试将此逻辑移动到可共享 __mocks__文件夹,它不再起作用了。

我从正在测试的文件中删除了所有不必要的代码,只保留了创建问题的两行:

import { withStyles } from '@material-ui/core/styles';

console.log('loaded styles:', withStyles);

export default 'hello';

并且测试也简化了,只是为了看看模拟是否工作,如下:
import test from '../test';
console.log(test);

我尝试的是创建一个 __mocks__项目根目录中的文件夹,其中我有 node_modules文件夹。

在那里我创建了一个名为 @material-ui 的第一个文件夹。在其中还有一个名为 core 的文件夹.
在此文件夹中,我有一个名为 styles.js 的文件使用以下代码:
export const withStyles = 'hello world';

所以结构看起来像:
- __mocks__
  - @material-ui
    - core
      - styles.js
- node_modules

这是有效的代码,在同一测试文件中定义了模拟:
jest.mock('@material-ui/core/styles', () => ({
  withStyles: () => Component => props => (
    <Component
      classes=""
      {...props}
    />
  ),
}));
__mocks__ 发生了什么?文件夹就是,如果我不调用任何
jest.mock('@material-ui/core/styles');

在我的测试文件中,它使用真正的 withStyles ,所以真正的模块。
根本没有使用任何模拟。

如果我使用:
jest.mock('@material-ui/core/styles');

它使用由 jest 自动生成的自动模拟(或者看起来如此),跳过了我在上面定义的模拟。

只是关于包的注释,我使用了CRA用于引导应用程序和 jest我目前拥有的版本是 20,带有 react-scripts版本 1.0.17

感谢大家的帮助!

最佳答案

以下是您应该如何在 __mocks__/@material-ui/core/styles.js 中使用手动模拟:

// Grab the original exports
import * as Styles from '@material-ui/core/styles';

const mockWithStyles = () => {
  console.log('withStyles being mocked'); // this shows that it works
  /**
   * Note: if you want to mock this return value to be
   * different within a test suite then use
   * the pattern defined here:
   * https://jestjs.io/docs/en/manual-mocks
   */

  return () => {}; // your mock function (adjust as needed)
  // you can also return the same implementation on certain conditions
  // return Styles.makeStyles; 
};

module.exports = { ...Styles, withStyles: mockWithStyles };
这是我手动模拟 makeStyles 的方法:
// Grab the original exports
// eslint-disable-next-line import/no-extraneous-dependencies
import * as Styles from '@material-ui/core/styles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import options from '../../../src/themes/options';

const mockMakeStyles = func => {
  /**
   * Note: if you want to mock this return value to be
   * different within a test suite then use
   * the pattern defined here:
   * https://jestjs.io/docs/en/manual-mocks
   */

  /**
   * Work around because Shallow rendering does not
   * Hook context and some other hook features.
   * `makeStyles` accept a function as argument (func)
   * and that function accept a theme as argument
   * so we can take that same function, passing it as
   * parameter to the original makeStyles and
   * binding it with our custom theme
   */
  const theme = createMuiTheme(options);
  return Styles.makeStyles(func.bind(null, theme));
};

module.exports = { ...Styles, makeStyles: mockMakeStyles };
makeStyles结果使用 React.useContext ,所以我们必须避免 mock useContext对于 makeStyles .使用 mockImplementationOnce如果您使用 React.useContext(...)首先在你的组件中,或者只是在你的测试代码中过滤掉它:
jest.spyOn(React, 'useContext').mockImplementation(context => {
  console.log(context);
  // only stub the response if
  if (context.displayName === 'MyAppContext') {
    return {
      auth: {},
      lang: 'en',
      snackbar: () => {},
    };
  }

  const ActualReact = jest.requireActual('react');
  return ActualReact.useContext(context);
});
在您的 createContext() 上电话,可能在 store.js , 添加 displayName (标准),或任何其他自定义属性来识别您的上下文:
const store = React.createContext(initialState);
store.displayName = 'MyAppContext';
makeStyles上下文 displayName 将显示为 StylesContextThemeContext并且它们的实现将保持不变以避免错误。
这修复了 makeStyles 的所有类型的模拟问题.但是我没用过withStyles要深入了解它的结构,但应该适用类似的逻辑。

关于javascript - 在 React with Jest 中为 @material-ui withStyles 创建手动模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54750544/

相关文章:

javascript - 如何在外部网站顶部显示 webapp 的标题栏?

java - 使用 jQuery for Java 应用程序的 Web 界面

java - 对对象图中的孤立对象进行单元测试

c++ - 在编译时使用注释自动包装 C/C++ 函数

unit-testing - 单元测试无效方法/模拟对象指示标志

javascript - 我的 RegEx 模式允许在电子邮件中使用双 "@"

javascript - 将新列插入 Kendo Datagrid

javascript - 如何操作位于状态并显示到页面的数据?

javascript - 如何显示来自 redux store 的数据?

javascript - React single source of Truth with html5 视频