繁体   English   中英

使用Jest测试本机反应-Redux App

[英]Using jest for test react-native - redux app

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

我已经成功做到了,但是没有使用redux,即使用react-native的本机状态。 this.state

组件代码:

//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);

});

我依靠这个链接

运行测试日志

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 ====>向我显示预期的值。

到现在为止还挺好

现在将所有内容传递给带有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);
}} />

连接逻辑

const mapStateToProps = (state) => {
  return {
    user: state.user
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    email_typing: (text) => dispatch(UserReducer.email_typing(text)),
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen)

我的UserReducer文件

import { createReducer, createActions } from 'reduxsauce'
import Immutable from 'seamless-immutable'

/* ------------- Types and Action Creators ------------- */

const { Types, Creators } = createActions({
  email_typing: ['email'],
})

export const LoginTypes = Types
export default Creators

/* ------------- Initial State ------------- */

export const INITIAL_STATE = Immutable({
  email: ''
})

/* ------------- Reducers ------------- */


// state.merge undefined error: https://github.com/infinitered/ignite/pull/20#issuecomment-202550408. Fixed including in Inmutable
export const emailTyping = (state, { email }) => {
  console.log('Email Typing changes !!! in original reducer')
  return Immutable(state).merge({ email })
}


/* ------------- Hookup Reducers To Types ------------- */

export const reducer = createReducer(INITIAL_STATE, {
  [Types.EMAIL_TYPING]: emailTyping,
})

进行此更改后,想法是测试文件中的initialState更改为INITIAL_STATE导入的值。

就像是:

const mockStore = configureStore([]);
let store = mockStore(INITIAL_STATE);

但是,当我再次运行测试时。 告诉我下一个错误:

 ● >>>>> LoginScreen component renders correctly

    TypeError: Cannot read property 'email' of undefined

即使我保留initialState而不是INITIAL_STATE,也不会出现上述错误,但是我无法获取用于更改的文本输入。

运行测试日志

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.

检查textInputProps2.getNode(1).props.value====>日志以检查它是否有用。

我认为在test file声明的const initialState不会受到在this.props.email_typing(text)操作时在实际化this.props.email_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);
});

我尝试了一个最小的实现,这是控制台结果:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM