测试Redux酶:状态更改后,组件不会重新呈现

时间:2018-08-20 14:19:06

标签: reactjs redux react-redux jestjs enzyme

我有一个称为DrawerAvatar的连接组件(到Redux商店),我将其导出以用于测试目的(酶+笑话),包括连接版本和非连接版本。

基本上,我想测试当我的Redux状态isAuthenticatedtrue时我的DrawerAvatar呈现用户头像,而当isAuthenticatedfalse时它呈现徽标图片

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将其连接到我的 real Redux存储,如下所示:(初始状态:{{1 }})

DrawerAvatar.test.js

isAuthenticated: false

这是我的authReducer:

authReducer.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
  });
});

因此,基本上,我有一个类型为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; } } 的真实动作,它将使用Axios调用一堆Redux-saga,但出于测试目的,我只是在我的真实authReducer中添加了一个LOGIN_WITH_EMAIL_REQUESTED例会将状态LOGIN_WITH_EMAIL_REQUESTED_TEST设置为isAuthenticated以避免Axios调用等...虽然不确定这是做事的好方法。.lol

我曾试图用true来强制组件更新...

我也看过redux-mock-store,但似乎您不能修改状态,只能处理操作而不是状态。

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

1 个答案:

答案 0 :(得分:1)

  

基本上,我想测试当我的Redux状态为isAuthenticated为true时,我的DrawerAvatar呈现用户头像,而当isAuthenticated为false时,它呈现徽标图片。

我建议不要连接整个连接的组件,并尝试完全不用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等的另一个简单测试