【问题标题】:Problems testing a Redux + React app with enzyme:使用酶测试 Redux + React 应用程序的问题:
【发布时间】:2020-07-29 22:43:15
【问题描述】:

我有这个组件

    import React, { useEffect } from 'react';
import './App.css';

import { connect } from 'react-redux';
import { CircularProgress } from '@material-ui/core';
import { loadPhones } from './redux/actions/actions.js';
import TablePhones from './Table.js';

const mapStateToProps = (state) => state;

function mapDispatchToProps(dispatch) {
  return {
    loadPhones: () => {
      dispatch(loadPhones());
    },
  };
}

export function App(props) {
  useEffect(() => {
    props.loadPhones();
  }, []);

  if (props.phones.data) {
    return (
      <div className="App">
        <div className="introductoryNav">Phones</div>
        <TablePhones phones={props.phones.data} />
      </div>
    );
  }
  return (
    <div className="gridLoadingContainer">
      <CircularProgress color="secondary" iconStyle="width: 1000, height:1000" />
      <p className="loadingText1">Loading...</p>
    </div>
  );
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

我写给谁

import React from 'react';
import { render } from '@testing-library/react';
import { Provider } from "react-redux";
import App from './App';
import { shallow, mount } from "enzyme";
import configureMockStore from "redux-mock-store";

const mockStore = configureMockStore();
const store = mockStore({});

describe('App comp testing', () => {
 

  it("should render without throwing an error", () => {
    const app = mount(
      <Provider store={store}>
        <App />
      </Provider>
    ).dive()
    expect(app.find('.introductoryNav').text()).toContain("Phones");
  });

})

但是那个测试总是失败

ypeError: 无法读取未定义的属性“数据”

我也尝试将 App 导入为 {App} 并使用浅层测试,但没有运气。它给出了相同的错误,所以我无法访问上下文,我不能继续做我的测试

我该如何解决这个问题?

【问题讨论】:

  • 为什么不会失败?想一想:你的商店是空的,所以没有 props.phones。
  • @jonrsharpe 是的,我想就是这样,但是我应该如何测试它呢?我要在商店里写一些模拟数据吗?
  • 很可能你发现了一个错误,但如果真实的商店有一个初始值,你也需要在测试中提供它。这里没有什么神奇之处,您必须安排测试条件以匹配您在现实生活中的实际期望。
  • @jonrsharpe 没有错误,redux 获取数据并显示它。所以我真的不明白我应该做什么。
  • 只需在测试中手动传递phones = { data: 'mock' } 属性...

标签: reactjs jestjs enzyme


【解决方案1】:

如果您将组件传递给道具并且不要尝试模拟商店(如果我没记错的话),您可以在此处使用组件的非默认导出和浅渲染测试。

我在想这样的事情可能会起作用,测试组件的“纯”非存储连接版本。这似乎是这个问题的一个流行答案,因为这是在 here 之前(以不同的方式)提出的:

import React from 'react';
import { App } from './App';
import { shallow } from "enzyme";

// useful function that is reusable for desturcturing the returned
// wrapper and object of props inside of beforeAll etc...
const setupFunc = overrideProps => {

  const props = {
    phones: {
      ...phones, // replace with a mock example of a render of props.phones
      data: {
        ...phoneData // replace with a mock example of a render of props.phones.data
      },
    },
    loadPhones: jest.fn()
  };

  const wrapper = shallow(<App {...props} />);

  return {
    wrapper,
    props
  };
};

// this is just the way I personally write my inital describe, I find it the easiest way
// to describe the component being rendered. (alot of the things below will be opinios on test improvements as well).
describe('<App />', () => {

  describe('When the component has intially rendered' () => {

    beforeAll(() => {
      const { props } = setupFunc();
    });


    it ('should call loadPhones after the component has initially rendered, () => {
      expect(props.loadPhones).toHaveBeenCalled();
    });
  });

  describe('When it renders WITH props present', () => {
  // we should use describes to section our tests as per how the code is written
  // 1. when it renders with the props present in the component
  // 2. when it renders without the props

    beforeAll(() => {
      const { wrapper, props } = setupFunc();
    });

    // "render without throwing an error" sounds quite broad or more like
    // how you would "describe" how it rendered before testing something
    // inside of the render. We want to have our "it" represent what we're
    // actually testing; that introductoryNave has rendered with text.

    it("should render an introductoryNav with text", () => {
      // toContain is a bit broad, toBe would be more specific
      expect(wrapper.find('.introductoryNav').text()).toBe("Phones");
    });

   it("should render a TablePhones component with data from props", () => {
      // iirc toEqual should work here, you might need toStrictEqual though. 
      expect(wrapper.find('TablePhones').prop('phones')).toEqual(props.phones);
    });
  });

  describe('When it renders WITHOUT props present', () => {

    it("should render with some loading components", () => {
     
      expect(wrapper.find('.gridLoadingContainer').exists()).toBeTruthy();
      expect(wrapper.find('CircularProgress').exists()).toBeTruthy();
      expect(wrapper.find('.loadingText1').exists()).toBeTruthy();
    });
  });
});

【讨论】:

    猜你喜欢
    • 2017-05-03
    • 2021-02-22
    • 2018-04-12
    • 2016-02-27
    • 2019-06-12
    • 1970-01-01
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多