【问题标题】:How to test a promise returned by an external module using axios.create in Jest?如何在 Jest 中使用 axios.create 测试外部模块返回的承诺?
【发布时间】:2019-08-01 15:40:24
【问题描述】:

我正在尝试测试由我的代码之外的模块返回的承诺,该模块使用 axios.create 进行调用。为了测试它是否正在查看 .then 和 .catch 我只是再次设置状态,但它没有考虑到这一点。为了测试 .then 和 .catch 内部发生了什么,我到底需要告诉 Jest 做什么?

我曾尝试模拟模块并监视“get”方法,但它们都不起作用。

文件.jsx

import React, { Component } from 'react';
import { request } from '../../../../global/Helper';

class File extends Component {
  constructor() {
    This.state = {
      isLoading: false,
      number: 5
    }
  }
  componentDidMount() {
    this.fetchStates();
  };
  fetchStates = () => {
    this.setState({isLoading: true});
    request.get('/api/state/')
    .then(response => {
      this.setState({ number: 10 });
    })
    .catch((err) => {
      this.setState({ number: 15 });
    });
  };
};

export { ProfileEdit };

Helper.js

import axios from 'axios';

let request = axios.create({
  baseURL: `${process.env.BASE_URL}`,
  headers: {
    'Content-Type': 'application/json'
  },
  withCredentials: true,
  crossDomain: true,
  responseType: 'json'
});

export { request };

文件.test.jsx

import React from 'react';
import * as Helper from '../../../../global/Helper';
import { File } from './File';

describe('File', () => {
  const props = {
    location: {
      state: {
      }
    },
  };

 it('should set the state twice', (done) => {
    // Arrange
    let component = mount(<ProfileEdit {...props}/>).instance();
    let setStateSpy = spyOn(ProfileEdit.prototype, 'setState');

    jest.spyOn(Helper.request, 'get').mockResolvedValue();

    // Act
    component.fetchStates();

    //Assert
    expect(setStateSpy).toHaveBeenCalledWith(jasmine.objectContaining({ number: 10 }));
    done();
  });

});

我希望 setstate 被调用两次,但它只调用一次。

这是我收到的错误消息:

 expect(spy).toHaveBeenCalledWith(expected)

    Expected spy to have been called with:
      ObjectContaining {"number": 10}
    as argument 1, but it was called with
      {"isLoading": true}.

    Difference:

    - Expected
    + Received

    - ObjectContaining {
    -   "number": 10,
    + Object {
    +   "isLoading": true,
      }

      46 |     component.fetchStates();
      47 | 
    > 48 |     expect(setStateSpy).toHaveBeenCalledWith(jasmine.objectContaining({ number: 10 }));
         |                         ^
      49 |     done();
      50 |   });
      51 | });

【问题讨论】:

  • 您为什么希望setState() 被调用两次?在您的测试期间,这些调用应该发生在哪里?哪几行?另外我建议直接针对组件的状态进行预期,那么您不必监视 setState()。
  • @Code-Apprentice 我忘了补充说我正在设置请求之前的状态。我遇到的主要问题是,即使我尝试使用“mockFn.mockResolvedValue(value)”,我也找不到测试 .then 内部内容的方法。

标签: javascript reactjs unit-testing jestjs axios


【解决方案1】:

似乎在您的then() 回调中对this.setState() 的调用没有被调用。这很可能是因为在解决或拒绝承诺之前测试已经完成。您可以从返回承诺开始:

fetchStates = () => {
    return request.get('/api/state/')
        .then(response => {
            this.setState({ number: 10 });
        })
        .catch((err) => {
            this.setState({ number: 15 });
        });
}

现在您可以在测试中获得承诺并在其上链接 then()

 it('should set the state twice', (done) => {
    // Arrange
    let component = mount(<ProfileEdit {...props}/>).instance();
    let setStateSpy = spyOn(ProfileEdit.prototype, 'setState');

    jest.spyOn(Helper.request, 'get').mockResolvedValue();

    // Act
    return component.fetchStates()
        .then(function() {
            //Assert
            expect(setStateSpy).toHaveBeenCalledWith(jasmine.objectContaining({ number: 10 }));
            done();
        });
  });

请注意,promise 也会从您的测试中返回。然后,Jest 将接受此承诺并允许它在打印有关您的测试的任何输出之前解决/拒绝。

建议: 期望调用this.setState() 要求您的测试取决于被测函数的详细信息。最好直接针对组件的最终状态进行预期,因为这样您的测试不再依赖于调用 this.setState() 的次数。如果你这样做,那么你必须小心确保 jest 解决了所有的承诺。

【讨论】:

  • 对不起!我忘了补充一点,我也在请求调用之前设置了一次状态!这就是为什么我要检查 setState 是否被调用两次。我遇到的主要问题是,即使我尝试使用“mockFn.mockResolvedValue(value)”,我也找不到测试 .then 内部内容的方法。
  • I forgot to add that I am also setting the state once before the request call! 请将该详细信息添加到您的代码示例中。
  • @PaolaArredondo 查看我编辑的答案,该答案显示了如何解决测试中的承诺。
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 2016-07-23
  • 2019-03-11
  • 2017-09-14
  • 2021-02-20
  • 2018-07-27
  • 2020-07-30
  • 2018-01-21
相关资源
最近更新 更多