开玩笑的异步功能

时间:2018-12-31 04:07:24

标签: javascript reactjs unit-testing jestjs enzyme

我是开玩笑/酶的新手,我尝试测试一个功能。该测试正在尝试测试getData()将返回的数组设置为处于状态。

这是它的外观:

getData () {
  axios.get('http://localhost:8080/targeting-data').then(response => {
    this.setState({
      targetingData: response.data,
      load: true
    })
  })
}

componentDidMount () {
  this.interval = setTimeout(() => {
    this.getData()
  }, 3000)
}

我的第一个测试:

import FormWrapper from './../containers/FormWrapper/FormWrapper'

const mockGetData = jest.spyOn(FormWrapper.prototype, 'getData')

it('testing', () => {
  mockGetData()
  expect(formWrapper.state().targetingData).toHaveLength(8)
})

我失败了:

expect(received).toHaveLength(length)

Expected value to have length:
  8
Received:
  []
received.length:
  0

第二次考试:

it('getDataFunc', (done) => {
  mockGetData().then(res => {
    expect(res).toHaveLength(8)
    done()
  })
})

我失败了:

TypeError: Cannot read property 'then' of undefined

(node:6302) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'setState' of undefined
(node:6302) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 4)

我对如何测试感到困惑,对于任何建议我都会感到高兴。谢谢

1 个答案:

答案 0 :(得分:0)

您可以使用async/await方法来测试函数getData的状态,async则是这样,但是首先您需要模拟axios get方法,因为您不想在测试中包括外部API调用,而只是模拟其响应:

import React from 'react';
import axios from 'axios';
import {shallow, mount} from "enzyme";
import FormWrapper from './../containers/FormWrapper/FormWrapper'

jest.mock('axios'); // for mocking axios

it('test', async () => {
    const wrapper = shallow(<FormWrapper />); // I'm using shallow render, you could use mount if you want to
    const instance = wrapper.instance(); // get an instance in order to call getData() directly
    // mock axios get with a response
    axios.get.mockImplementation(() => Promise.resolve([
        {
            id: 1,
            val: 'val1'
        },
        {
            id: 2,
            val: 'val2'
        }
    ]));
    await instance.getData();
    expect(wrapper.state().targetingData).toHaveLength(2); // this is the length of the mocked response I have added here
});

关于此功能,我想在此指出。我认为,您要测试的函数getData()实际上不是要测试的好对象,因为它不包含您编写的任何逻辑。

它从API获取一些数据(这不是您拥有的),然后使用this.setState设置状态(并且您不想测试React执行setState的行为来更新您的状态状态)。

如果要为state填充一些数据以用于测试组件中的其他功能,那么我建议您像这样手动设置它:

const wrapper = shallow(<FormWrapper />);
wrapper.setState({
    targetingData: {...}
});

因此,您可以将更多的精力集中在函数和代码部分上,这些函数和部分包含您自己编写的更多逻辑。