React+Jest+Enzyme测试

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/qq_22755565/article/details/84304064

项目介绍:

1、antd-pro创建的项目

为什么不直接用roadhog test?

看了源码roadhog test不支持–watch–coverage之外的Jest命令,我们的项目需要用到–updateSnapshot等

import test from 'umi-test';

const args = process.argv.slice(2);

const watch = args.indexOf('-w') > -1 || args.indexOf('--watch') > -1;
const coverage = args.indexOf('--coverage') > -1;

test({
  watch,
  coverage, //不支持其他用户配置的命令
}).catch(e => {
  console.log(e);
  process.exit(1);
});

文档地址

UI测试

  1. 使用snapshot,使用jest -u更新快照
import renderer from 'react-test-renderer'

// use 'jest -u' to update
test('snapshot of LoginPage', () => {
  const rendered = renderer.create(<LoginPage store={store} />).toJSON()
  expect(rendered).toMatchSnapshot()
})
  1. 特别重要的可以使用mount深度渲染
    尽量使用shallow前渲染,并且只测试当前组件,子组件应该在子组件的测试文件中测试
import React from 'react'
import { mount } from 'enzyme'
import configureStore from 'redux-mock-store'
import renderer from 'react-test-renderer'

import LoginPage from '../src/routes/User/Login'

const initialProps = {
  login: {
    status: 'error',
    message: '',
  },
  loading: {
    effects: {
      'login/login': false,
    },
  },
}
const mockStore = configureStore()
const store = mockStore(initialProps)

describe('UI render and event', () => {
  let loginComponent
  let outLayer
  let usernameInput
  let passwordInput
  let submitButton
  let errorComponent
  beforeEach(() => {
    outLayer = mount(<LoginPage store={store} login={{ status: 'xx', message: 'errorMessage' }} />)
    loginComponent = outLayer.find('form')
    usernameInput = outLayer.find('input#userName')
    passwordInput = outLayer.find('input[type="password"]')
    submitButton = outLayer.find('button[type="submit"]')
    errorComponent = outLayer.find('div.ant-alert-error')
  })
  afterEach(() => {
    outLayer.unmount()
  })

  it('should render successfully', () => {
    expect(outLayer.length).toBe(1)
    expect(usernameInput.length).toBe(1)
    expect(passwordInput.length).toBe(1)
    expect(submitButton.length).toBe(1)
    expect(errorComponent.length).toBe(1)
  })
})

使用模拟store–redux-mock-store

注意这里的store并不是真正意义上的store,实际上他不会触发action
不推荐使用真正store,如果有必要可以使用createStorestore = createStore(initialProps)

import configureStore from 'redux-mock-store'

const initialProps = {
  login: {
    status: 'error',
    message: '',
  },
  loading: {
    effects: {
      'login/login': false,
    },
  },
}
const mockStore = configureStore()
const store = mockStore(initialProps)

describe('UI render and event', () => {
  let outLayer
  beforeEach(() => {
    outLayer = mount(<LoginPage store={store} />)
  })
  afterEach(() => {
    outLayer.unmount()
  })
})

使用simulate模拟事件

test('action triggered by submit', () => {
  usernameInput.simulate('change', { target: { value: 'bsc_storage' } })
  passwordInput.simulate('change', { target: { value: '12345' } })
  loginComponent.simulate('submit')

  const actions = store.getActions()
  expect(actions[0].type).toBe('login/login')
})

modal测试–effects

使用jest.mock()模拟API数据,使用runSage触发action
mock文件位置为pathTo/api.js则mock文件位置为pathTo/__mocks__/api.js,并且__mocks__是大小写敏感的

import { runSaga, effects } from 'redux-saga'
jest.mock('../src/services/api')
test('should effects login successful', async () => {
  const dispatched = []
  await runSaga({
    dispatch: action => dispatched.push(action),
  }, modal.effects.login, { payload: payloadRightPassword }, { call, put }).done

  const toogleMesageAction = dispatched.filter(action => action.type === 'toggleMessage')[0]
  expect(toogleMesageAction).toBeTruthy()
  const { token, status, currentUser } = toogleMesageAction.payload.data
  expect(token).toBe('mdTiCAVW7SV4cRfK3YPYRTTAhtLpYRMqBmHxznMj')
  expect(status).toBe('ok')
  expect(currentUser.name).toBe('bsc_storage')
  expect(dispatched.filter(action => action.type === 'changeLoginStatus').length).toBe(1)
})

⚠️注意:这里的effetcs不可以当作普通的异步方法进行测试

modal测试-reducers

reducer就是一个普通的函数所以直接测试输出就可以

test('appendValue', () => {
  const state = {
    status: undefined,
  }
  const action = {
    payload: {
      status: 'error',
    },
  }
  const result = modal.reducers.appendValue(state, action)
  // toBe({ status: 'error' }) or Object.is() both return false
  expect(result).toEqual({ status: 'error' })
})

猜你喜欢

转载自blog.csdn.net/qq_22755565/article/details/84304064
今日推荐