【问题标题】:Testing functions with arguments in React with Jest Enzyme在 React with Jest Enzyme 中测试带参数的函数
【发布时间】:2018-11-01 01:12:51
【问题描述】:

我在反应组件中有一个名为 toggleFilter() 的函数,如下所示:

toggleFilter = (filterType, filterName) => {
        const filterApplied = this.state.appliedFilterList[filterType].includes(filterName);

        if (filterApplied) {
            //Remove the applied filter
            this.setState(prevState => ({
                appliedFilterList: {
                    ...prevState.appliedFilterList,
                    [filterType]: prevState.appliedFilterList[filterType].filter(filter => filter !== filterName)
                }
            }));
        } else {
            //Add the filter
            this.setState(prevState => ({
                appliedFilterList: {
                    ...prevState.appliedFilterList,
                    [filterType]: [...prevState.appliedFilterList[filterType], filterName]
                }
            }));
        }
    };

这个函数被传递给子组件:

 <ChildComponent  toggleFilter={this.toggleFilter} />

所以,我正在尝试像这样测试这个 toggleFilter() 函数:

 it("checks for the function calls", () => {
    const toggleFilterMockFn = jest.fn();
    const component = shallow(
        <ProductList
            headerText="Hello World"
            productList={data}
            paginationSize="10"
            accessFilters={["a 1", "a 2"]}
            bandwidthFilters={["b 1", "b 2"]}
            termsFilters={["t 1", "t 2"]}
            appliedFilterList={appliedFilter}
            toggleFilter={toggleFilterMockFn}
        />
    );
    component.find(FilterDropdownContent).prop("toggleFilter")({ target: { value: "someValue" } });
});

但我收到错误消息:

TypeError: Cannot read property 'includes' of undefined

什么可能导致问题?有人可以帮我解决这个问题吗?

编辑 1: 我尝试了以下测试用例:

expect(toggleFilterMockFn).toHaveBeenCalledWith(appliedFilter, "access");

但我收到以下错误:

expect(jest.fn()).toHaveBeenCalledWith(expected)

    Expected mock function to have been called with:
      [{"access": ["Access Type Of The Service"], "bandwidth": ["the allowed band width ", "the allowed band width"], "term": ["term associated with the service"]}, "access"]
    But it was not called.

【问题讨论】:

  • 为什么将{ target: { value: "someValue" } } 对象作为函数参数传递?您的实际函数需要两个参数filterType and filterName,您可能需要在测试中将它们的值作为参数传递。并且您的测试应该检查是否使用参数调用了模拟函数?
  • 如果你在使用 jest,那么你试试这个 API。 facebook.github.io/jest/docs/en/…
  • @GaleelBhasha,感谢您的回复。所以你的意思是说,我必须传递 (appliedFilterlist, filter) 之类的参数,而不是 { target: { value: "someValue" } } ?我说的对吗?
  • 是的,{ target: { value: "someValue" } } 通常用于将事件对象作为.simulate() 方法的第二个参数传递。 github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/…
  • 好的。我已经尝试过运行你提到的测试,但仍然出现错误。我已经在上面的编辑中发布了我的测试用例和错误消息。请您检查一次。另外,我对您提到的上述评论有 1 个疑问。如果函数没有任何参数,那么({ target: { value: "someValue" } }) 部分保持空白或者我们不需要包含该部分?

标签: javascript reactjs tdd jestjs enzyme


【解决方案1】:

您不能像这样渲染父函数并测试子函数。相反,您应该直接渲染&lt;FilterDropdownContent /&gt;,然后编写一个模拟事件(如点击)的测试并检查该函数是否被调用。

例如这样的:

import React from 'react';
import { shallow } from 'enzyme';

describe('<FilterDropdownContent />', () => {
  let wrapper, toggleFilter;
  beforeEach(() => {
    toggleFilter = jest.fn();
    wrapper = shallow(
      <FilterDropdownContent
        toggleFilter={toggleFilter}
      />
    );
  });

  describe('when clicking the .toggle-filter button', () => {
    it('calls `props.toggleFilter()` with the correct data', () => {
      wrapper.find('.toggle-filter').simulate('click');
      expect(toggleFilter).toHaveBeenCalledWith({ target: { value: 'someValue' } });
    });
  }):
});

在此示例中,单击带有 .toggle-filter 类的链接会调用该函数,但您应该能够根据您的具体实现对其进行调整。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-31
    • 1970-01-01
    • 2018-10-20
    • 2019-02-25
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    相关资源
    最近更新 更多