模拟 Axios 以测试 .catch()

Posted

技术标签:

【中文标题】模拟 Axios 以测试 .catch()【英文标题】:Mock Axios to test .catch() 【发布时间】:2020-03-03 23:37:57 【问题描述】:

我一直在尝试编写测试来测试 axios 调用,但现在需要测试 catch 部分。

我已经能够通过像这样模拟 axios 来做到这一点,但似乎无法获得测试 catch 的方法。我从堆栈溢出和网络中跟踪了许多不同的示例。

jest.mock('axios', () => jest.fn(() => Promise.resolve( data: mockData )));

但这总是会返回一个好的结果,所以不能测试捕获。我要测试的代码是:goToUrl() 只是一个window.location.assign(url),但已导入。

fetchBundlesFromApi(params)
  .then(( data:  bundles  ) => 
    updateBundles(bundles);
    this.setState( showUpdatingPrices: false );
  )
  .catch(() => goToUrl(bundlesUrl));

在我对.then() 部分的测试中,我这样做:

const fetchedBundles = await fetchBundlesFromApi(
  '?params',
);
expect(fetchedBundles.data).toEqual(mockData);

但是,如果我按照 Mocking Axios with Jest in React - mock function not being called 这样的示例进行操作,我无法手动模拟 get 如果我将模拟 axios 文件放在文件夹 __mocks__ 中,那么很多测试套件都失败了,所以我只想模拟它在这个测试文件中。

这是我尝试做的一个例子:

    jest.mock('axios', () => (
  get: () => jest.fn(() => Promise.resolve( data: mockData )),
  default: () => jest.fn(() => Promise.resolve( data: mockData )),
));

但是TypeError: (0 , _axios.default) is not a function 的测试错误

编辑:

这是我的 fetchBundlesApi 函数:

const fetchBundlesFromApi = params => axios(`$bundleRoute/bundles$params`);

编辑:捕捉测试

    it('should redirect if api fails', async () => 
    const networkError = new Error('Some network error');
    axios.mockRejectedValueOnce(networkError);
    const goToUrl = jest.fn();
    let error;

    try 
      await fetchBundlesFromApi('?params');
     catch (err) 
      error = err;
    

    expect(error).toEqual(networkError);
    expect(goToUrl).toHaveBeenCalled();
  );

在我的组件中,我像这样导入goToUrl

import goToUrl from 'Helpers';

【问题讨论】:

你试过Promise.reject而不是Promise.resolve吗? 我没有尝试过,因为如果我这样做,那么我当前的测试将失败 【参考方案1】:

您可以利用 Jests 功能在它们运行后弹出实现,即mockImplementationOnce 和朋友。

import axios from 'axios';

jest.mock('axios');

// default implementation
axios.get.mockResolvedValue(mockedData);

describe('#fetchBundlesFromApi', () => 
  it('returns data from API', async () => 
    const fetchedBundles = await fetchBundlesFromApi('?params');
    expect(fetchedBundles.data).toEqual(mockData);
  );
  it('redirects on failure', () => 
    // override behaviour for this one call
    axios.get.mockRejectedValueOnce();
    // verify your failure test
  );
);

【讨论】:

嘿,我试过了,但我得到一个错误说`TypeError:无法读取未定义的属性'then''我尝试将解析的值更改为promise,但仍然是同样的问题。我刚刚用我的 fetch 函数更新了我的问题,所以你可以看到它在做什么 @saunders 所以看起来你没有调用任何显式函数,即get,你似乎只是依赖于 axios 的默认行为。您可以将模拟更改为axios.mockResolvedValue(...),也可以将代码更改为更明确的axios.get('...:) 感谢您为这条好路工作,但我刚刚尝试了 catch 部分,它似乎可以解决我的 mockData。 axios.mockRejectedValueOnce(Promise.reject(new Error('something bad happened'))); 但在测试中它说它收到了mockData 数组 我已经尝试了很多不同的东西,但我似乎无法调用 goToUrl() 它一直在说 Expected mock function to have been called, but it was not called 我已经编辑了我的问题以包含我拥有的代码,但它不是很有效跨度> @saunders没问题,让我看看

以上是关于模拟 Axios 以测试 .catch()的主要内容,如果未能解决你的问题,请参考以下文章

单元测试:如何在反应中模拟 axios?

Axios 中的单元测试拦截器逻辑

使用 jest.mock('axios') 时如何模拟拦截器?

模拟内部 axios.create()

如何在笑话测试中模拟 json.parse()

如何在 Jest 中模拟 .then() 和 .catch()? [关闭]