如何单元测试Reaction钩子组件在使用中获取数据的效果? [英] How to unit test react hooks component that fetches data in useEffect using Enzyme?

查看:14
本文介绍了如何单元测试Reaction钩子组件在使用中获取数据的效果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Reaction Hooks组件,它在启动时从API服务器获取数据。(使用中有效)

我正在尝试使用酶创建单元测试,但酶似乎没有等待数据可用。

{
"react": "^16.8.6",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.14.0",
}

我正在测试的组件

import React, {useEffect, useState} from 'react';
import Checkbox from '@material-ui/core/Checkbox';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import Grid from "@material-ui/core/Grid";
import {getTermsAndConditions} from "../../../../api/auth/authApiConsumer";
import {makeStyles} from "@material-ui/core";
import Typography from '@material-ui/core/Typography';
import Link from "@material-ui/core/Link";
import Modal from '@material-ui/core/Modal';
import Aux from '../../../../hoc/Aux/Aux';
import Box from "@material-ui/core/Box";

const useStyles = makeStyles(theme => ({
  txtLabel: {
    fontSize: '0.85rem',
  },
  paper: {
    position: 'absolute',
    width: 800,
    height: 800,
    backgroundColor: theme.palette.background.paper,
    border: '0px solid #000',
    boxShadow: theme.shadows[5],
    padding: theme.spacing(2, 4, 4),
    outline: 'none',
  },
  modalContent: {
    height: 700,
    overflowY: 'scroll',
  },
}));



export const TermsAndConditionsCheckbox = props => {

  const {onStateChange} = props;
  const [state, setState] = useState({
    errors: [],
    onChange: false,
    pristine: false,
    touched: false,
    inProgress: false,
    value: {
      termsAndConditions: []
    }
  });
  const [article, setArticle] = useState([]);

  useEffect(() => {
    async function fetchData() {
      const response = await getTermsAndConditions("ENGLISH", "USER").catch(e => {
      });
      // returns Enabled TAC
      const enabledTAC = getEnabledTAC(response);
      const latestTACRecord = [];

      // When multiple Articles with different version exist, we show the latest one only.
      for (const key in enabledTAC) {
        latestTACRecord.push(
            {
              id: enabledTAC[key].articles[0].id,
              name: enabledTAC[key].name,
              lang: enabledTAC[key].lang,
              articleScope: enabledTAC[key].articleScope,
              content: enabledTAC[key].articles[0].content,
              datePublished: enabledTAC[key].articles[0].datePublished,
              state: enabledTAC[key].articles[0].state,
              mandatory: enabledTAC[key].mandatory,
            }
        )
      }
      setArticle(latestTACRecord);
    }

    fetchData()
  }, []);

  const createTACForm = (article, isMandatory) => {

    if (isMandatory) {
      return (
          <FormControlLabel
              key={'madatoryAgreement'}
              id={'madatoryAgreement'}
              name={'madatoryAgreement'}
              control={<Checkbox value="mandatoryAgreement"
                                 color="primary"
                                 }/>}
              label={<Typography
                  className={classes.txtLabel}>{createTACLine(article,
                  isMandatory)}</Typography>}
          />
      );
    } else if ((article.filter(art => art.mandatory === false)).length > 0) {
      return (
          <Aux>
            {article.filter(art => art.mandatory === false).map(
                (value, index) => {
                  return (
                      <FormControlLabel
                          key={'optionalAgreement_' + index}
                          id={'optionalAgreement_' + index}
                          name={'optionalAgreement'}
                          control={<Checkbox value="optionalAgreement"
                                             color="primary"
                                             }/>}
                          label={<Typography
                              className={classes.txtLabel}>{createTACLine(
                              [value],
                              isMandatory)}</Typography>}
                      />
                  )
                })}
          </Aux>

      )
    } else {
      return null;
    }
  };

  const createTACLine = (article, isMandatory) => {

    return (
        <Aux>
          {isMandatory ? "[Mandatory] " : "[Optional] "}
          {article.filter(art => art.mandatory === isMandatory)
          .map(art => {
            return (
                <Link component="button" variant="body2" id={'art_' + art.id}
                      key={art.id} onClick={(e) => {
                  e.preventDefault();
                  setModalArticleName(art.name);
                  setModalArticleContent(art.content);
                  setOpen(true);
                }}
                      name={'art_' + art.id}>
                  {art.name}
                </Link>
            );
          })
          .reduce((prev, curr) => [prev, ", ", curr])
          }
        </Aux>
    );
  };


  const handleChecked = (isAgreed, ArticleArray) => {
    let isRequirementMet = true;
    const tacResult = [];
    for (const key in ArticleArray) {
      if (ArticleArray[key].mandatory && isAgreed === false) {
        // User did not agree on mandatory TACs
        isRequirementMet = false;
      }
      tacResult.push({articleId: ArticleArray[key].id, agreed: isAgreed});
    }
    const updatedState = {
      ...state,
      pristine: isRequirementMet,
      value: {
        termsAndConditions: tacResult,
      }
    };
    setState(updatedState);
    onStateChange(updatedState);

  };

  const classes = useStyles();

  return (
      <Grid container spacing={1}>
        <Grid item xs={12}>

          {article[0] && createTACForm(article, true)}
          <Box m={1}/>
          {article[0] && createTACForm(article, false)}

        </Grid>
      </Grid>
  )

};

export default TermsAndConditionsCheckbox;

我的单元测试代码

import {configure} from "enzyme/build";
import Adapter from "enzyme-adapter-react-16/build";
import {createShallow} from "@material-ui/core/test-utils";
import TermsAndConditionsCheckbox from "./TermsAndConditionsCheckbox";
import FormControlLabel from '@material-ui/core/FormControlLabel';

import React from "react";

jest.mock("../../../../api/auth/authApiConsumer");


configure({adapter: new Adapter()});

describe('<TermsAndConditionsCheckbox />', () => {
  const handleStateChange = jest.fn();
  let shallow;

  beforeAll(() => {
    shallow = createShallow();
  });
  let wrapper;
  beforeEach(() => {
    wrapper = shallow(<TermsAndConditionsCheckbox onStateChange={handleStateChange}/>);
  });

  it('should render one <FormControlLabel /> element.', () => {
    expect(wrapper.find(FormControlLabel)).toHaveLength(1);
  });

  it('should render names from API', (done) => {

      wrapper.update();
      console.log(wrapper.find(FormControlLabel).debug());
      expect(wrapper.find(FormControlLabel)).toHaveLength(1);
      done();

  });

});

authApiConsumer(接口模拟)


export const getTermsAndConditions = (language, articleScope) => new Promise(
    function (resolve, reject) {
      const articlesToReturn = [
                {
          "id": 16,
          "name": "test1",
          "lang": "ENGLISH",
          "articleScope": "USER",
          "articles": [
            {
              "id": 30,
              "content": "test ut article",
              "datePublished": "2019-03-17",
              "state": "PUBLISHED"
            },
            {
              "id": 29,
              "content": "test ut article2",
              "datePublished": "2018-02-16",
              "state": "PUBLISHED"
            }
          ],
          "mandatory": false,
          "enabled": true
        }
      ];

      if(language === "ENGLISH"){
        resolve(articlesToReturn);
      }else{
        reject();
      }
    });

我预计酶将等待使用效果,测试应该会通过。

推荐答案

需要使用酶的挂载功能。浅层渲染不会触发ComponentDidmount,因此不会调用Effect。请尝试以下代码。

import { configure } from "enzyme/build";
import Adapter from "enzyme-adapter-react-16/build";
import { createShallow } from "@material-ui/core/test-utils";
import TermsAndConditionsCheckbox from "./TermsConditions";
import FormControlLabel from '@material-ui/core/FormControlLabel';
import { act } from "react-dom/test-utils";
import { mount } from 'enzyme';
import React from "react";

jest.mock("./api/authApiConsumer");


configure({ adapter: new Adapter() });

describe('<TermsAndConditionsCheckbox />', () => {
    const handleStateChange = jest.fn();
    let component;
    act(() => {
        component = mount(<TermsAndConditionsCheckbox onStateChange={handleStateChange} />);
    });

    it('should render one <FormControlLabel /> element.', () => {
        expect(component.find(FormControlLabel)).toHaveLength(0);
    });

    it('should render names from API', (done) => {
        act(() => {
            component.update();
        });
        expect(component.find(FormControlLabel)).toHaveLength(2);
        done();
    });
});

某些路径需要根据您的项目文件夹结构进行修复。

这篇关于如何单元测试Reaction钩子组件在使用中获取数据的效果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆