Unit testing 使用jest测试反应本机-redux应用程序

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!!! ==

我正在尝试填充文本输入,并验证文本是否正确填充,访问组件并获取其值

我成功地做到了这一点,但没有使用redux(即使用react native的本机状态)<代码>此。状态

组件代码:

//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' } }