猿问

在 Enzyme 中,如何从功能组件的道具中获取功能?

我正在使用 Jest 和 Enzyme 为我的 React 项目编写单元测试。


如下图,我通过propsupdateUser给待测组件传递了一个命名的函数。EditCard


describe('The EditCard screen', () => {

  let wrapper;


  beforeEach(() => {

    const defaultProps: Partial<EditCardProps> = {

      toggleEditing: jest.fn(),

      user: mockUsers[0],

      updateUser: jest.fn(),      // passes this function to the "EditCard" component via props

      showSnackbar: jest.fn(),

    };

    wrapper = shallow(<EditCard {...(defaultProps as EditCardProps)} />);

  });

然后我想测试模拟点击按钮后调用了多少次。


  it('should match the snapshot when the "Name" textfield is not filled and the "submit" button is clicked', () => {

    wrapper.find('#Name').simulate('change', { target: { value: null } });

    wrapper.find('#submit').simulate('click');

    

    // Try to get the "updateUser" function from the props, but get "undefined". 

    expect(wrapper.prop('updateUser')).toHaveBeenCalledTimes(0);

  });

但是我得到如下所示的错误:


    Matcher error: received value must be a mock or spy function


    Received has value: undefined


      24 |     wrapper.find('#Name').simulate('change', { target: { value: null } });

      25 |     wrapper.find('#submit').simulate('click');

    > 26 |     expect(wrapper.prop('updateUser')).toHaveBeenCalledTimes(0);

有人能告诉我我哪里做错了吗?为什么我无法从道具中获取功能并被undefined退回?


提前致谢!


牛魔王的故事
浏览 90回答 1
1回答

慕虎7371278

对您的代码进行一些调整应该可以正常工作...import * as React from "react";import { mount, ReactWrapper } from "enzyme";import EditCard from "../path/to/EditCard";/*&nbsp;&nbsp; I'd recommend defining jest fns here to make them easier to reference anywhere&nbsp; within the tests below; otherwise, it'll have to referenced via&nbsp;&nbsp; 'defaultProps.updateUser', 'defaultProps.showSnackbar', ...etc.&nbsp;&nbsp; Using 'const' here allows us to define these variables within the&nbsp;&nbsp; module's closure -- in short, only accessible within these tests and NOT&nbsp;&nbsp; globally accessible (from other file tests).*/const showSnackbar = jest.fn();const toggleEditing = jest.fn();const updateUser = jest.fn();/*&nbsp;&nbsp; if the EditCard component is properly typed, then you shouldn't need to&nbsp; add types to this 'defaultProps' object*/const defaultProps = {&nbsp; showSnackbar,&nbsp; toggleEditing,&nbsp; updateUser,&nbsp; user: mockUsers[0]};describe('The EditCard screen', () => {&nbsp; let wrapper: ReactWrapper;&nbsp; beforeEach(() => {&nbsp; &nbsp; /*&nbsp;&nbsp; &nbsp; &nbsp; I'd recommend mount over shallow because child components can be&nbsp;&nbsp; &nbsp; &nbsp; deeply nested and require multiple .dive calls; however, if&nbsp;&nbsp; &nbsp; &nbsp; you know the child components of "EditCard" are just simple JSX elements,&nbsp;&nbsp; &nbsp; &nbsp; then shallow will be fine&nbsp; &nbsp; */&nbsp; &nbsp; wrapper = mount(<EditCard {...defaultProps} />);&nbsp; });&nbsp; it("should not call 'updateUser' when the form is submitted with an empty '#Name' field", () => {&nbsp; &nbsp; /*&nbsp; &nbsp; &nbsp; I'm not sure what simulating "null" does for this input, but assuming this&nbsp; &nbsp; &nbsp; input is required you should at least pass a string value -- assuming&nbsp; &nbsp; &nbsp; "#Name" input is of type 'text' | 'password' | 'email' => string and&nbsp;&nbsp; &nbsp; &nbsp; not a number. On a related note, if it's required, then simply remove this&nbsp;&nbsp; &nbsp; &nbsp; code as it doesn't do much for the test.&nbsp; &nbsp; */&nbsp; &nbsp; // wrapper.find('#Name').simulate('change', { target: { value: "" } });&nbsp; &nbsp; /*&nbsp; &nbsp; &nbsp; I'm assuming this then simulates a form submit. Unfortunately,&nbsp; &nbsp; &nbsp; pressing the submit button won't work. Instead you'll have to&nbsp;&nbsp; &nbsp; &nbsp; simulate a form submit. This is a limitation of Enzyme and last I&nbsp;&nbsp; &nbsp; &nbsp; checked hasn't been/can't be fixed.&nbsp; &nbsp; */&nbsp; &nbsp; wrapper.find('form').simulate('submit');&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; /*&nbsp; &nbsp; &nbsp;it should then NOT call the jest.fn() "updateUser" when submitted since&nbsp;&nbsp; &nbsp; &nbsp;'#Name' is empty. Notice that we're referencing 'updateUser' -- the jest fn&nbsp; &nbsp; &nbsp;defined above -- and not the wrapper.prop fn.&nbsp; &nbsp; */&nbsp;&nbsp; &nbsp; expect(updateUser).not.toHaveBeenCalled();&nbsp; });&nbsp;&nbsp;&nbsp; // include other tests...});
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答