使用Jest模拟React的AJAX请求

时间:2019-10-14 13:38:08

标签: reactjs jestjs

我正在构建一个React组件,该组件安装后将通过AJAX从服务器获取数据。

我正在尝试(并且失败)在Jest中模拟AJAX调用,并且想知道我是否只是误解了Jest中的模拟是如何工作的?

我的文件结构是:

  • index.js
  • index.test.js
  • requests.js
  • __ mocks__
    • requests.js

组件(index.js)通过requests.js进行呼叫,而requests.js使用Axios从服务器获取数据。 __mocks__index.test.js文件夹中被模拟。

从下面的测试文件getSpy中可以看出,我正在使用requests.getData来检测是否调用了getData函数。从来没有。我应该补充一点,我也尝试过使组件仅呈现console.log(ListWrapper.debug());函数响应中的某些数据,然后在测试文件中运行import React from 'react'; import { mount } from 'enzyme'; import List from './index'; import expect from 'expect'; import requests from './requests'; jest.mock('requests'); describe('Renders list', () => { const getSpy = jest.spyOn(requests, 'getData'); const ListWrapper = mount( <ListWrapper /> ); console.log(ListWrapper.debug()); it('should fetch currencies', () => { expect(getSpy).toBeCalled(); }); }); 以查看数据是否为在测试中呈现。再一次,它永远不会。

只是想知道是否有人可以发现我要去哪里错了,或者我只是走错了方向?

index.test.js

module.exports = {
    getData: () => {
        return new Promise((resolve) => {
            resolve({
               [
                    {
                        id: 1,
                        name: 'Bob Smith',
                        age: 32
                    }
                ]
            });
        });

    }
};

__ mocks __ / requests.js

/**
 * List component
 */
import React, { useState, useEffect, useCallback } from 'react';
import * as requests from './requests’;
function List(props) {

  const [data, setData] = useState([]);

   /**
     * Get data from server
     */
   const getCurrencies = useCallback(() => {
      r4_uiTools.loadingAnimation.show();
      requests
          .getData()
          .then((response) => {
              setData(response);
          })
          .catch(error) {
              //...
          }

   /**
     * Get data when first mounting component
     */
    useEffect(() => {
        getData();
    }, [getData]);

  return(
   <>
    /* ... */
    {data[0].name}
   </>
  );

index.js(已缩短)

import axios from 'axios';

const getData = () => {
    return new Promise((resolve, reject) => {
        const url = `/MyURL/`;
        axios
            .get(url)
            .then((response) => {
                resolve(response);
            })
            .catch((error) => {
                reject(error);
            });
    });
};

export { getData };

requests.js(已缩短)

firebase_messaging 5.1.6

4 个答案:

答案 0 :(得分:0)

您的divisors <- function(n) { which((n %% 1:floor(n / 2)) == 0) } 是不是应该这样?

useEffect

另外,您的useEffect(() => { getCurrencies(); }, []); 中的ListWrapper是什么?是错字,应该是index.test.js吗?

答案 1 :(得分:0)

如果您模拟通话并返回Promise,则必须使其异步阻止

还请把安装座放在it块内,否则必须使自己的描述异步

describe('Renders list', () => {
    ...
    ...
    it('should fetch currencies', async () => {
        expect(getSpy).toBeCalled();   
    });
});

答案 2 :(得分:0)

您的jest.mock请求似乎不正确。如果它不是一个node_module,它应该指向路径,就像您的导入一样: jest.mock('./requests');

由于jest.mock通过'。/ request`模拟所有导出,因此您现在也不需要间谍。如果是我,我会这样写测试:

import React from 'react';
import { mount } from 'enzyme';
import List from './index';
import expect from 'expect';

import requests from './requests';

jest.mock('./requests', () => {    // Path instead of name when mocking own modules
    return {
        default: {
            getData: jest.fn().mockResolvedValue('some value')    // explicit mock
        },
        // ... any other exports you'd wanna mock 
    };
});

describe('Renders list', () => {

    const ListWrapper = mount(
        <ListWrapper />
    );

    console.log(ListWrapper.debug());

    it('should fetch currencies', () => {
        expect(requests.getData).toBeCalled();  // Directly check on getData since it should point to a mock function   
    });
});

答案 3 :(得分:0)

如果您应该选择spyOnjest.mock来执行此操作。 对于jest.mock,它应该是:

jest.mock('./requests', () => ({ 
        getData: jest.fn(),
    }));

如果要在调用此响应数据时对其进行处理。您必须使用wait中的@testing-library/react。您可以在here

上阅读更多内容