dispatch(action) 不会立即更新单元测试中的 redux 状态
dispatch(action) doesn't immediately update redux state in unit tests
我正在为基于 React 和 redux 的应用程序编写测试用例。
container = TestUtils.renderIntoDocument(
<Provider store={createStore({"key": "old_val"})}>
{() => <Component />}
</Provider>
);
使用 initialState
渲染后,我发送一个动作并查看状态是否发生变化。
Component.store.dispatch({ type: 'SET_VAL', value: 'some_val' });
然后我打印状态
console.log(store.getState());
我希望状态为 {"key": "some_val"}
。但是,它仍然显示 {"key": "old_val"}
.
应用程序运行良好,只是测试失败,所以我的 action-creators
或 reducers
.
不会有任何问题
我是不是做错了什么?顺便说一句,我正在使用 thunk
中间件进行异步操作分派。这会干扰这里吗?如果是,我如何等到异步操作完成?
更新:
redux 测试 shown here 非常简单,但它们似乎工作正常。
store.dispatch(addTodo('Hello'));
expect(store.getState()).toEqual([{
id: 1,
text: 'Hello'
}]);
redux 的巨大好处之一是它允许您使用纯函数和纯组件来实现几乎所有应用程序。 Redux 和 react-redux 抽象了订阅 UI 状态更改的实现细节,这使您可以隔离测试应用程序的所有代码。这样,您就不需要在每次要测试代码时都渲染带有商店的提供程序,这大大降低了复杂性。
假设您所在的州有一个 key
属性 和一个 KeyDisplay
组件。您可以使用以下 reducer 文件实现状态:
reducers.js
import { combineReducers } from 'redux';
export function key(state, { type, value }) {
switch(type) {
case 'SET_VAL': return value;
default: return state;
}
}
export default combineReducers({ key });
您可以为我们的组件设置一个文件:
KeyDisplay.js
import React from 'react';
import { connect } from 'react-redux';
export function KeyDisplay({ keyProp }) {
return (
<div>The key is {keyProp}</div>
);
}
export default connect((state) => { keyProp: state.key })(KeyDisplay);
然后在 reduce 的单元测试中,您可以只导入 key
的 reducer 并完全独立于用户界面进行测试:
keyReducer.test.js
import test from 'tape';
import { key } from './reducers.js';
test('key reducer', (t) => {
t.plan(1);
const output = key('old', { type: 'SET_VAL', value: 'new' });
t.equal(output, 'new', 'SET_VAL should override old value');
});
此外,由于 connect
将状态作为 props 传递到组件中,您可以只渲染未connect
ed 组件和一些代表您感兴趣的状态的测试 props,同样无需设置商店和供应商:
KeyDisplay.test.js
import test from 'tape';
import { renderIntoDocument } from 'react-addons-test-utils';
import { KeyDisplay } from './KeyDisplay.js';
test('KeyDisplay', (t) => {
const component = renderIntoDocument(<KeyDisplay keyProp="test" />);
// test component
});
我正在为基于 React 和 redux 的应用程序编写测试用例。
container = TestUtils.renderIntoDocument(
<Provider store={createStore({"key": "old_val"})}>
{() => <Component />}
</Provider>
);
使用 initialState
渲染后,我发送一个动作并查看状态是否发生变化。
Component.store.dispatch({ type: 'SET_VAL', value: 'some_val' });
然后我打印状态
console.log(store.getState());
我希望状态为 {"key": "some_val"}
。但是,它仍然显示 {"key": "old_val"}
.
应用程序运行良好,只是测试失败,所以我的 action-creators
或 reducers
.
我是不是做错了什么?顺便说一句,我正在使用 thunk
中间件进行异步操作分派。这会干扰这里吗?如果是,我如何等到异步操作完成?
更新:
redux 测试 shown here 非常简单,但它们似乎工作正常。
store.dispatch(addTodo('Hello'));
expect(store.getState()).toEqual([{
id: 1,
text: 'Hello'
}]);
redux 的巨大好处之一是它允许您使用纯函数和纯组件来实现几乎所有应用程序。 Redux 和 react-redux 抽象了订阅 UI 状态更改的实现细节,这使您可以隔离测试应用程序的所有代码。这样,您就不需要在每次要测试代码时都渲染带有商店的提供程序,这大大降低了复杂性。
假设您所在的州有一个 key
属性 和一个 KeyDisplay
组件。您可以使用以下 reducer 文件实现状态:
reducers.js
import { combineReducers } from 'redux';
export function key(state, { type, value }) {
switch(type) {
case 'SET_VAL': return value;
default: return state;
}
}
export default combineReducers({ key });
您可以为我们的组件设置一个文件:
KeyDisplay.js
import React from 'react';
import { connect } from 'react-redux';
export function KeyDisplay({ keyProp }) {
return (
<div>The key is {keyProp}</div>
);
}
export default connect((state) => { keyProp: state.key })(KeyDisplay);
然后在 reduce 的单元测试中,您可以只导入 key
的 reducer 并完全独立于用户界面进行测试:
keyReducer.test.js
import test from 'tape';
import { key } from './reducers.js';
test('key reducer', (t) => {
t.plan(1);
const output = key('old', { type: 'SET_VAL', value: 'new' });
t.equal(output, 'new', 'SET_VAL should override old value');
});
此外,由于 connect
将状态作为 props 传递到组件中,您可以只渲染未connect
ed 组件和一些代表您感兴趣的状态的测试 props,同样无需设置商店和供应商:
KeyDisplay.test.js
import test from 'tape';
import { renderIntoDocument } from 'react-addons-test-utils';
import { KeyDisplay } from './KeyDisplay.js';
test('KeyDisplay', (t) => {
const component = renderIntoDocument(<KeyDisplay keyProp="test" />);
// test component
});