【问题标题】:Testing Redux Enzyme: Component doesn't re-render after state has changed测试 Redux Enzyme:状态改变后组件不会重新渲染
【发布时间】:2019-01-26 16:53:11
【问题描述】:

我有一个名为 DrawerAvatar 的连接组件(到 Redux 商店),我为了测试目的(Enzyme + Jest)导出了连接和非连接版本。

基本上,我想测试我的DrawerAvatar在我的Redux状态isAuthenticated为true时渲染用户头像,当isAuthenticated为false时渲染一个logo图片。

DrawerAvatar.js

export class DrawerAvatar extends React.Component {
  render () {
    const avatarSrc = this.props.isAuthenticated ?
      'http://user-avatar.png'
    ) : (
      'http://logo.png'
    );

    return (
      <StyledAvatarContainer>
        <StyledAvatar src={avatarSrc} />
      </StyledAvatarContainer>
    );
  }
}

const mapStateToProps = state => ({
  isAuthenticated: state.authReducer.isAuthenticated
});

export default compose(
  connect(mapStateToProps, null)
)(DrawerAvatar);

在我的测试中,我正在使用未连接的 DrawerAvatar,并通过 Provider 将其连接到我的 真实 Redux 商店,如下所示:(初始状态:isAuthenticated: false)

DrawerAvatar.test.js:

import React from 'react';
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';

import store from '../../store';
import connectedDrawerAvatar, { DrawerAvatar } from './DrawerAvatar';

describe('Header > DrawerAvatar: component', () => {
  it('should render logo for the DrawerAvatar if not authenticated, and the user avatar if authenticated', () => {
    const wrapper = shallow(<Provider store={store}><DrawerAvatar /></Provider>);
    console.log(wrapper.dive().debug());
    // Output: 
    // <StyledAvatarContainer>
    //  <StyledAvatar src="https://logo.png" />
    // </StyledAvatarContainer>    
    const StyledAvatarSrc = wrapper.dive().find('StyledAvatar').prop('src');
    expect(StyledAvatarSrc).toBe('https://logo.png'); // assertion passed

    store.dispatch({ type: 'LOGIN_WITH_EMAIL_REQUESTED_TEST' });
    // the state has been correctly updated, now isAuthenticated: true

    console.log(wrapper.dive().debug());
    // Output: same as above, whereas it should be: 
    // <StyledAvatarContainer>
    //  <StyledAvatar src="https://user-avatar.png" />
    // </StyledAvatarContainer>    
    expect(StyledAvatarSrc).toBe('https://user-avatar.png'); // assertion failed
  });
});

这是我的 authReducer:

authReducer.js

const initialState = {
  isAuthenticated: false
};

export default function authReducer (state = initialState, action) {
  switch (action.type) {
    case 'LOGIN_WITH_EMAIL_REQUESTED_TEST':
      return {
        ...state,
        isAuthenticated: true,
      };
    default:
      return state;
  }
}

所以基本上,我有一个LOGIN_WITH_EMAIL_REQUESTED 类型的实际操作,它将使用 Axios 调用一堆 Redux-saga,但出于测试目的,我只是在我的真实 authReducer 中添加了一个 LOGIN_WITH_EMAIL_REQUESTED_TEST 案例,它将设置将isAuthenticated 声明为true 以避免Axios 调用等...虽然不确定这是否是一种好方法..lol

我试图强制组件更新为wrapper.update()...

我也查看了 redux-mock-store,但您似乎无法修改状态,只处理动作而不处理状态。

我刚刚开始编写我的第一个 React 测试,所以...谢谢!

【问题讨论】:

  • 我相信您需要在测试中调用store.dispatch 后立即调用wrapper.update()。这行得通吗?
  • 是的,我做到了,但不幸的是它不起作用。
  • 你还需要在调用dispatch之后取出你想要的prop,然后更新。例如,在 wrapper.update 之后,添加一行 const StyledAvatarSrcUnauth = wrapper.dive().find('StyledAvatar').prop('src'); 然后 expect(StyledAvatarSrcUnauth) 等

标签: reactjs redux react-redux jestjs enzyme


【解决方案1】:

基本上,我想测试一下,当我的 Redux 状态 isAuthenticated 为 true 时,我的 DrawerAvatar 渲染用户头像,当 isAuthenticated 为 false 时,它​​渲染一个 logo 图片。

我建议不要连接整个连接的组件并尝试使用 Redux。您可以通过以下方式实现预期结果:

describe('Header > DrawerAvatar: component', () => {
  it('should render logo for the DrawerAvatar if not authenticated, and the user avatar if authenticated', () => {
    let wrapper = shallow(<DrawerAvatar isAuthenticated={false} />);
    let StyledAvatarSrc = wrapper.find('StyledAvatar').prop('src');
    expect(StyledAvatarSrc).toBe('https://logo.png');
    wrapper = shallow(<DrawerAvatar isAuthenticated={true} />);
    StyledAvatarSrc = wrapper.find('StyledAvatar').prop('src');
    expect(StyledAvatarSrc).toBe('https://user-avatar.png');
  });
});

然后,您可以为所涉及的每个部分编写单独的测试,例如您的 mapStateToProps 函数,它实际上只是一个根据其输入返回对象的简单函数。以及对您的authReducer 等的另一个简单测试

【讨论】:

  • 你就是男人!我只是想了一下(因为状态变成了道具!!)并按照您描述的方式完全实施并且即将更新我的问题,但是您更快:D!因此,我以某种方式放心,我的方向是正确的,哈哈,非常感谢!!
  • 太棒了,很高兴听到它正在工作。另一种方法也应该有效,但它违反了单元测试的理念,并且更多地进行了集成测试。如果您是 Jest 的新手,一定要尽可能地学习 toMatchSnapshot。祝你好运
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
  • 2020-07-12
  • 2020-01-20
  • 2019-06-29
相关资源
最近更新 更多