【发布时间】: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