Unit testing 使用jest测试反应本机-redux应用程序
我正在尝试填充文本输入,并验证文本是否正确填充,访问组件并获取其值 我成功地做到了这一点,但没有使用redux(即使用react native的本机状态)<代码>此。状态 组件代码:Unit testing 使用jest测试反应本机-redux应用程序,unit-testing,testing,react-native,react-redux,jestjs,Unit Testing,Testing,React Native,React Redux,Jestjs,我正在尝试填充文本输入,并验证文本是否正确填充,访问组件并获取其值 我成功地做到了这一点,但没有使用redux(即使用react native的本机状态)此。状态 组件代码: //inside constructor this.state = { email: '' } <TextInput value={this.state.email} onChangeText={(text) => { console.log('Here change email text!!! ==
//inside constructor
this.state = {
email: ''
}
<TextInput value={this.state.email} onChangeText={(text) => {
console.log('Here change email text!!! ==> ', text);
this.setState({
email: text
})
}} />
import LoginScreen from '../../App/Containers/LoginScreen' // => connected component.. exported with `export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen)`
import configureStore from 'redux-mock-store'
import { shallow } from 'enzyme'
import Actions, { reducer, INITIAL_STATE } from '../../App/Redux/Reducers/UserReducer'
const initialState = {
user: {
email: 'mockState email',
password: '',
requesting: 0,
userData: null,
loginFinish: false,
errorMessage: null
}
}
const mockStore = configureStore([]);
let store = mockStore(initialState);
const wrapper = shallow(
<LoginScreen/>,
{ context: { store: store } },
);
test('>>>>> LoginScreen component renders correctly', () => {
expect(wrapper.dive()).toMatchSnapshot();
});
test('>>>>> Login button Press', () => {
let render = wrapper.dive();
const textInputProps = render.find('TextInput'); //getting text input from render
console.log(`textInputProps.getNode(1).props.value BEFORE ====>`, textInputProps.getNodes()[0].props.value);
textInputProps.first().simulate('changeText', 'My new value'); // executing onChangeText inside render of component
const textInputProps2 = render.find('TextInput'); //getting text input again for check changes
console.log(`textInputProps2.getNode(1).props.value====>`, textInputProps2.getNodes()[0].props.value);
const state = store.getState(); //verifying internal `initialState`.. NOT CHANGES
console.log('state ===> ', state);
});
正如您在日志textInputProps2.getNode(1).props.value===>
中看到的,按预期显示值
到目前为止还不错
现在,通过redux结构将所有内容传递给reducer,我们将看到如下文本输入
<TextInput value={this.props.user.email} style={styles.textInputs} placeholder={'Email'} autoCapitalize={'none'} onChangeText={(text) => {
console.log('Here change email text!!! ==> ', text);
this.props.email_typing(text);
}} />
我的UserReducer
文件
考虑到这种更改,想法是测试文件中的初始状态
更改为初始状态
导入值
比如:
const mockStore = configureStore([]);
let store = mockStore(INITIAL_STATE);
但是,当我再次运行测试时。显示下一个错误:
● >>>>> LoginScreen component renders correctly
TypeError: Cannot read property 'email' of undefined
即使我保留initialState而不是initialu状态,我也不会得到上面的错误,但是我无法得到文本输入来接受更改
运行测试日志
yarn test v0.24.6
$ jest
PASS Tests/Containers/loginScreenTest.js
✓ >>>>> LoginScreen component renders correctly (282ms)
✓ >>>>> Login button Press (33ms)
console.log Tests/Containers/loginScreenTest.js:60
textInputProps.getNode(1).props.value BEFORE ====>
console.log App/Containers/LoginScreen.js:124
Here change email text!!! ==> My new value
console.log Tests/Containers/loginScreenTest.js:67
textInputProps2.getNode(1).props.value====> My new value => (!!!WORKS!!!)
console.log Tests/Containers/loginScreenTest.js:86
state ===> { user:
{ email: 'mockState email',
password: '',
requesting: 0,
userData: null,
loginFinish: false,
errorMessage: null } }
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 1 passed, 1 total
Time: 2.337s, estimated 3s
Ran all test suites.
✨ Done in 3.10s.
检查textInputProps2.getNode(1.props.value===>
log以检查这是否有用
我认为测试文件中声明的const initialState
在调用this.props.email\u typing(text)
操作时,不会受到实际减速机中所做更改的影响
我还没有找到方法将动作与减速器中的状态连接起来,并能够在JEST中加载它们。
我知道它有点长,我很感谢你花时间阅读它。
我尽量给它留下最好的解释和尽可能多的信息。
非常感谢,我期待您的回复。我想您应该在这里做一些集成测试。有可能实现您正在尝试的目标:
import { createStore, combineReducers } from 'redux';
import { reducer } from '.../UserReducer';
// create a real store with the needed reducer(s)
const store = createStore(combineReducers({ user: reducer }));
const wrapper = shallow(
<LoginScreen/>,
{ context: { store } },
);
// ...
test('>>>>> Login button Press', () => {
let render = wrapper.dive();
const textInputProps = render.find('TextInput');
console.log(`value BEFORE ====>`, textInputProps.getNodes()[0].props.value);
textInputProps.first().simulate('changeText', 'My new value');
// Force the component to update after changing state
render = wrapper.update().dive();
const textInputProps2 = render.find('TextInput');
console.log(`value AFTER ====>`, textInputProps2.getNodes()[0].props.value);
const state = store.getState();
console.log('state ===> ', state);
});
从'../../App/Containers/LoginScreen'/=>连接的组件导入LoginScreen。。使用`导出默认连接(mapStateToProps,mapDispatchToProps)(LoginScreen)导出这听起来像是一个导入问题,您是否也导出了组件(测试文件中应该有两个导出,一个用于连接,一个用于实际组件)。状态更改工作正常,但之后的值仍然为空。我正在从LoginScreen
打印渲染内部的this.props.user.email
,但仍然为空。但是当我打印store.getState()
时,如果我在wrapper.update().dive()之前再次调用shallow
,我就可以看到更改对我有效似乎有些东西不需要,你知道为什么吗?
● >>>>> LoginScreen component renders correctly
TypeError: Cannot read property 'email' of undefined
yarn test v0.24.6
$ jest
PASS Tests/Containers/loginScreenTest.js
✓ >>>>> LoginScreen component renders correctly (345ms)
✓ >>>>> Login button Press (24ms)
console.log Tests/Containers/loginScreenTest.js:58
textInputProps.getNode(1).props.value BEFORE ====> mockState email
console.log App/Containers/LoginScreen.js:120
Here change email text!!! ==> My new value
console.log Tests/Containers/loginScreenTest.js:61
textInputProps2.getNode(1).props.value====> mockState email => **(!! HERE !!!, THE VALUE IS BEING THE PREVIOUS ONE AND IGNOR THE CHANGE)**
console.log Tests/Containers/loginScreenTest.js:79
state ===> { user:
{ email: 'mockState email',
password: '',
requesting: 0,
userData: null,
loginFinish: false,
errorMessage: null } }
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 1 passed, 1 total
Time: 2.904s
Ran all test suites.
✨ Done in 3.68s.
import { createStore, combineReducers } from 'redux';
import { reducer } from '.../UserReducer';
// create a real store with the needed reducer(s)
const store = createStore(combineReducers({ user: reducer }));
const wrapper = shallow(
<LoginScreen/>,
{ context: { store } },
);
// ...
test('>>>>> Login button Press', () => {
let render = wrapper.dive();
const textInputProps = render.find('TextInput');
console.log(`value BEFORE ====>`, textInputProps.getNodes()[0].props.value);
textInputProps.first().simulate('changeText', 'My new value');
// Force the component to update after changing state
render = wrapper.update().dive();
const textInputProps2 = render.find('TextInput');
console.log(`value AFTER ====>`, textInputProps2.getNodes()[0].props.value);
const state = store.getState();
console.log('state ===> ', state);
});
console.log src/Test.test.js:27
value BEFORE ====>
console.log src/Test.test.js:35
value AFTER ====> My new value
console.log src/Test.test.js:38
state ===> { user: { email: 'My new value' } }