Javascript 如何使用带有挂钩的react功能组件测试句柄函数调用

Javascript 如何使用带有挂钩的react功能组件测试句柄函数调用,javascript,reactjs,jestjs,enzyme,Javascript,Reactjs,Jestjs,Enzyme,我正试图为我用MaterialUI制作的一个相当简单的选项卡栏编写单元测试 基本上,我只想测试单击选项卡时是否调用了handleTabChange函数,以及是否传入了正确的值。我还想测试路由是否有效,即测试“Feed”按钮是否将您带到/Feed,但我也无法让它起作用 TabBar.jsx import React,{useState}来自“React”; 从“@material ui/core”导入{Tabs,Tab}”; 从“react router dom”导入{withRouter};

我正试图为我用MaterialUI制作的一个相当简单的选项卡栏编写单元测试

基本上,我只想测试单击选项卡时是否调用了
handleTabChange
函数,以及是否传入了正确的值。我还想测试路由是否有效,即测试“Feed”按钮是否将您带到
/Feed
,但我也无法让它起作用

TabBar.jsx

import React,{useState}来自“React”;
从“@material ui/core”导入{Tabs,Tab}”;
从“react router dom”导入{withRouter};
从“属性类型”导入{object};
从“../../constants/constants”导入{tabToPathnameMap,pathnameToTabMap};
常量选项卡=(道具)=>{
const{history,location}=props;
const{pathname}=位置;
const handleTabChange=(e,newValue)=>{
setCurrentTab(新值);
history.push(tabToPathnameMap[newValue]);
};
常量[currentTab,setCurrentTab]=useState(
pathnameToTabMap[路径名]?pathnameToTabMap[路径名]:false
);
返回(
handleTabChange(e,newValue)}
居中的
>
);
};
TabBar.propTypes={
历史:目标,
位置:对象
};

使用路由器导出默认值(选项卡栏)我认为应该将命名常量与默认导出一起导出

import React, { useState } from 'react';
import { Tabs, Tab } from '@material-ui/core';
import { withRouter } from 'react-router-dom';
import { object } from 'prop-types';
import { tabToPathnameMap, pathnameToTabMap } from '../../constants/constants';

//CHANGED THIS LINE
export const TabBar = (props) => {
  const { history, location } = props;
  const { pathname } = location;

  const handleTabChange = (e, newValue) => {
    setCurrentTab(newValue);
    history.push(tabToPathnameMap[newValue]);
  };

  const [currentTab, setCurrentTab] = useState(
    pathnameToTabMap[pathname] ? pathnameToTabMap[pathname] : false
  );

  return (
    <Tabs
      value={currentTab}
      onChange={(e, newValue) => handleTabChange(e, newValue)}
      centered
    >
      <Tab label="Feed" tabBar-tab-testId="Feed" />
      <Tab label="Fork" tabBar-tab-testId="Fork" />
      <Tab label="Favs" tabBar-tab-testId="Favs" />
    </Tabs>
  );
};

TabBar.propTypes = {
  history: object,
  location: object
};

export default withRouter(TabBar);
import React,{useState}来自“React”;
从“@material ui/core”导入{Tabs,Tab}”;
从“react router dom”导入{withRouter};
从“属性类型”导入{object};
从“../../constants/constants”导入{tabToPathnameMap,pathnameToTabMap};
//换了这条线
导出常量选项卡=(道具)=>{
const{history,location}=props;
const{pathname}=位置;
const handleTabChange=(e,newValue)=>{
setCurrentTab(新值);
history.push(tabToPathnameMap[newValue]);
};
常量[currentTab,setCurrentTab]=useState(
pathnameToTabMap[路径名]?pathnameToTabMap[路径名]:false
);
返回(
handleTabChange(e,newValue)}
居中的
>
);
};
TabBar.propTypes={
历史:目标,
位置:对象
};
使用路由器导出默认值(选项卡栏);
然后在测试中,导入命名常量而不是默认常量

import React from 'react';
import { mount } from 'enzyme';
import { MemoryRouter } from 'react-router-dom';
import TestComponentWrapper from '../../TestComponentWrapper';
//CHANGED THIS LINE
import { TabBar } from '../../../Components/TabBar/TabBar';

describe('TabBar', () => {
  it('should move to /fork when the fork tab is clicked', () => {
    const wrapper = mount(
      <TestComponentWrapper>
        <MemoryRouter initialEntries={['/']}>
          <TabBar />
        </MemoryRouter>
      </TestComponentWrapper>
    );
    const spy = jest.spyOn(wrapper.instance(), 'handleTabChange');
    expect(spy).toHaveBeenCalledTimes(0);
    wrapper.find('[tabBar-tab-testId="Fork"]').hostNodes().simulate('click');
    expect(spy).toHaveBeenCalledTimes(1);
  });
});
从“React”导入React;
从“酶”导入{mount};
从'react router dom'导入{MemoryRouter};
从“../../TestComponentWrapper”导入TestComponentWrapper;
//换了这条线
从“../../../Components/TabBar/TabBar”导入{TabBar};
描述('TabBar',()=>{
它('单击fork选项卡时应移到/fork',()=>{
常量包装器=装入(
);
const spy=jest.spyOn(wrapper.instance(),'handleTabChange');
预期(间谍)。已被催收时间(0);
wrapper.find('[tabBar tab testId=“Fork”]').hostNodes().simulate('click');
期望(间谍)。被催促的时间(1);
});
});

没有测试它,但它应该可以工作

感谢您的回复-我需要使用withRouter()导出它,因为我使用的是位置和路径。即使我没有这样做,它也不会改变这样一个事实,即react函数组件(无状态)上的wrapper.instance()仍然会给出null:(哦,从下面的链接来看,似乎你应该传递所需的道具。在你的例子中,
历史
位置
位置。路径名
是从道具中解构出来的,所以试着发送它们。在这个问题中,他们也在测试一个无状态组件。我传递了道具,但没有传递包装器。instance()仍然为null。对于功能组件,它将始终为
null
。是否有其他方法可以在没有它的情况下测试功能?您是如何解决此问题的?