使用Hooks API和酶浅渲染测试Material UI组件

时间:2019-05-07 10:37:25

标签: material-ui enzyme react-hooks

Material UI的最新版本现在具有样式组件的Hooks替代品,而不是HoC。所以代替

const styles = theme => ({
  ...
});

export const AppBarHeader = ({ classes, title }) => (
  ...
);
export default withStyles(styles)(AppBarHeader);

您可以选择改为:

const useStyles = makeStyles(theme => ({
  xxxx
}));

const AppBarHeader = ({ title }) => {
  const classes = useStyles();
  return (
    ....
  )
};

export default AppBarHeader;

在某些方面,这是更好的选择,但是与所有钩子一样,您不再可以向组件注入“存根”依赖项。以前,为了使用酶进行测试,我只是测试了非样式化组件:

describe("<AppBarHeader />", () => {
  it("renders correctly", () => {
    const component = shallow(
      <AppBarHeader title="Hello" classes="{}" />
    );
    expect(component).toMatchSnapshot();
  });
});

但是,如果使用钩子,而类没有'stub'依赖项,则会得到:

  Warning: Material-UI: the `styles` argument provided is invalid.
  You are providing a function without a theme in the context.
  One of the parent elements needs to use a ThemeProvider.

因为您总是需要一个提供者。我可以把它包起来:

describe("<AppBarHeader />", () => {
  it("renders correctly", () => {
    const component = shallow(
      <ThemeProvider theme={theme}>
        <AppBarHeader title="Hello" classes="{}" />
      </ThemeProvider>
    ).dive();
    expect(component).toMatchSnapshot();
  });
});

,但这似乎不再呈现组件的子代(即使使用了潜水调用)。人们是如何做到的?

1 个答案:

答案 0 :(得分:0)

编辑:根据下面的评论,此实现存在一些计时问题。考虑使用安装而不是浅层测试来进行测试,或者使用withStyles HOC并导出组件以进行浅层渲染。

所以我已经为此努力了一天。这是我想出的。

由于makeStyles似乎MUI已将其设置为只读,因此存在一些问题。因此,我没有在每个组件中创建一个useStyles钩子,而是创建了自己的自定义useStyles钩子,该钩子调用makeStyles。这样,我可以将useStyles挂钩存根用于测试,而对代码流的影响最小。

// root/utils/useStyles.js
// My custom useStyles hook

import makeStyles from '@material-ui/styles/makeStyles';

export const useStyles = styles => makeStyles(theme => styles(theme))();

几乎就像使用withStyles HOC

// root/components/MyComponent.js
import React from 'react';
import { useStyles } from '../util/useStyles';

// create styles like you would for withStyles
const styles = theme => ({
  root: {
    padding: 0,
  },
});

export const MyComponent = () => {
  const classes = useStyles(styles);
  return(
    </>
  );
}
// root/component/MyComponent.spec.js
import { MyComponent } from './MyComponent';
import { shallow } from 'enzyme';
import { stub } from 'sinon';

describe('render', () => {
  it('should render', () => {
    let useStylesStub;
    useStylesStub = stub(hooks, 'useStyles');
    useStylesStub.returns({ });
    const wrapper = shallow(<MyComponent />);
    console.log('profit');
  });
});

这是我目前能想到的最好的方法,但总是会提出建议。