【问题标题】:How to find a child component from the enzyme mounted, react-redux stateToProps connected parent?如何从安装的酶中找到子组件,react-redux stateToProps 连接的父组件?
【发布时间】:2022-02-15 11:45:23
【问题描述】:

在以下组件中,当 isHybrid 属性为真时,我将 <HeaderContainer /> 隐藏在 dom 中:

{...}
import { initializeRoutes, lazy } from 'hooks/useRouteHook';
import { isHybridSelector } from 'store/selectors';
import HeaderContainer from './header';

const routes = [
  { component: lazy(...component) },
  {...}
];

export const UpgradeBlock = ({ isHybrid }) => {

  return (
    <Fragment>
      {!isHybrid && (
        <HeaderContainer />
      )}
      <div
      >
        <Suspense fallback={<Loader />}>{initializeRoutes(routes)}</Suspense>
      </div>
    </Fragment>
  );
};

const mapStateToProps = state => ({
  isHybrid: isHybridSelector(state),
});

CashUpgradeBlock.propTypes = {
  isHybrid: PropTypes.bool,
}

export default connect(mapStateToProps)(UpgradeBlock);

在这里,我想通过模拟 isHybrid 属性值来检查 &lt;HeaderContainer /&gt; 组件的存在。

import React from 'react';
import { Router } from 'react-router-dom';
import { mount } from 'enzyme';
//Internal MockProvider Component.
import { MockProvider } from 'utils/tests';    
import HeaderContainer from './header';
import UpgradeBlock from './index';

//Mock router-dom
jest.mock('react-router-dom', () => {
  // Require the original module to not be mocked...
  const originalModule = jest.requireActual('react-router-dom');
  return {
    __esModule: true, // Use it when dealing with esModules
    ...originalModule,
    Redirect: jest.fn().mockReturnValue(<div>Redirect</div>),
  };
});

//Mock selectors
jest.mock('store/selectors', () => ({
  ...jest.requireActual('store/selectors'),
  isHybridSelector: jest.fn(),
}));

function UpgradeBlockWithStore({ history, ...props } = {}) {
  return mount(
    <Router {...}>
      <MockProvider
        {...props}
        {...}
      >
        <UpgradeBlock {...props} />
      </MockProvider>
    </Router>
  );
}

describe('CashUpgradeBlock', () => {
  it('renders CashUpgradeBlock', () => {
    const wrapper = UpgradeBlockWithStore();
    const headerContainer = wrapper.find(HeaderContainer);

    isHybridSelector.mockImplementation(() => false);
    
    //Since isHybrid is set to false HeaderContainer should be present in the dom.
    expect(headerContainer.exists()).toBe(true); //or .toBeTruthy()
  })
})

console.log(wrapper.debug()) 在控制台的结果如下:

console.log organisms/upgrade-block/upgrade-block.spec.js:57

<Router history={{...}}>
  <MockProvider resources={{...}}>
    <Provider store={{...}}>
      <Connect(UpgradeBlock) history={{...}} location={{...}} resources={{...}} />
    </Provider>
  </MockProvider>
</Router> 

即使在互联网上搜索了数小时后,我也找不到任何解决方案……我也不是测试专家;虽然isHybrid在redux中默认设置为false,但我也尝试通过({isHybrid: false})将它提供给UpgradeBlockWithStore(props)仍然没有帮助,测试用例在dom树中找不到headerContainer和期待它是虚假的。

【问题讨论】:

    标签: reactjs react-redux jestjs enzyme


    【解决方案1】:

    我的测试策略:

    1. 创建一个模拟 redux 存储而不是模拟选择器。
    2. 创建内存历史记录或使用MemoryRouter 而不是模拟react-router-dom

    我添加了您的代码并删除了不相关的部分。

    例如

    index.jsx:

    import React, { Fragment } from 'react';
    import { connect } from 'react-redux';
    import HeaderContainer from './header';
    import { isHybridSelector } from './selectors';
    
    export const UpgradeBlock = ({ isHybrid }) => {
      console.log('isHybrid: ', isHybrid);
      return <Fragment>{!isHybrid && <HeaderContainer />}</Fragment>;
    };
    
    const mapStateToProps = (state) => ({
      isHybrid: isHybridSelector(state),
    });
    
    export default connect(mapStateToProps)(UpgradeBlock);
    

    header.jsx:

    import React from 'react';
    
    export default function Header() {
      return <div>Header</div>;
    }
    

    selectors.js:

    const { createSelector } = require('reselect');
    
    const selectEnvironment = (state) => state.environment;
    export const isHybridSelector = createSelector(selectEnvironment, (environment) => environment.isHybrid);
    

    index.test.jsx:

    import React from 'react';
    import { Router } from 'react-router-dom';
    import { Provider } from 'react-redux';
    import { mount } from 'enzyme';
    import { createMemoryHistory } from 'history';
    import { createStore } from 'redux';
    
    import HeaderContainer from './header';
    import UpgradeBlock from './';
    
    const rootReducer = (state = { environment: { isHybrid: false } }) => state;
    const store = createStore(rootReducer);
    const MockProvider = ({ children }) => {
      return <Provider store={store}>{children}</Provider>;
    };
    
    function UpgradeBlockWithStore({ history, ...props } = {}) {
      return mount(
        <Router history={history}>
          <MockProvider>
            <UpgradeBlock {...props} />
          </MockProvider>
        </Router>
      );
    }
    
    describe('71118716', () => {
      test('should pass', () => {
        const history = createMemoryHistory();
        const wrapper = UpgradeBlockWithStore({ history });
        const headerContainer = wrapper.find(HeaderContainer);
        expect(headerContainer.exists()).toBe(true);
      });
    });
    

    测试结果:

     PASS  stackoverflow/71118716/index.test.jsx (9.425 s)
      71118716
        ✓ should pass (58 ms)
    
      console.log
        isHybrid:  false
    
          at UpgradeBlock (stackoverflow/71118716/index.jsx:7:11)
    
    --------------|---------|----------|---------|---------|-------------------
    File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    --------------|---------|----------|---------|---------|-------------------
    All files     |     100 |      100 |     100 |     100 |                   
     header.jsx   |     100 |      100 |     100 |     100 |                   
     index.jsx    |     100 |      100 |     100 |     100 |                   
     selectors.js |     100 |      100 |     100 |     100 |                   
    --------------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        10.023 s
    

    【讨论】:

    • 感谢您的努力,非常感谢。但现在这是真正的测试必要性。将 isHybrid 值更改为 true 并没有找到 headerContainer。
    • @RegarBoy 然后你应该提供一个模拟状态,isHybridtrue。尝试在每个测试用例中创建模拟状态而不是硬代码
    • 感谢您的建议。所以我在我共享的代码中使用了以下isHybridSelector.mockImplementation(() =&gt; false);,使用它将isHybrid 设置为false/true 并没有真正改变已安装组件中isHybrid 的值
    猜你喜欢
    • 2019-09-26
    • 1970-01-01
    • 2017-11-19
    • 2018-01-30
    • 2023-02-25
    • 2021-04-02
    • 1970-01-01
    • 2018-09-13
    • 2021-01-01
    相关资源
    最近更新 更多