【问题标题】:Mocking Axios with Jest in React - mock function not being called在 React 中使用 Jest 模拟 Axios - 未调用模拟函数
【发布时间】:2019-07-22 16:19:05
【问题描述】:

我正在尝试使用 Jest 进行单元测试。部分测试是模拟 Axios,但由于某种原因它没有被调用。

这是我的/__mocks__/axios.js 代码:

export default {
  post: jest.fn(() => Promise.resolve({})),
};

这是我的测试代码:

import mockAxios from 'axios';
import { registerUser } from '../../actions/auth';
import user from '../fixtures/user';


describe('Register User', () => {
  test('Should call register API and redirect to login', async () => {
    const historyMock = { push: jest.fn() };

    mockAxios.post.mockImplementationOnce(() => Promise.resolve());

    await registerUser(user, historyMock);

    expect(mockAxios.post).toHaveBeenCalledTimes(1);

  });
});

这里还有 registerUser 代码:

export const registerUser = (user, history) => dispatch => axios
  .post('/users/register', user)
  .then(() => history.push('/login'))
  .catch((err) => {
    dispatch(handleError(err));
  });

但由于某种原因,我继续收到错误:

Register User › Should call register API and redirect to login

    expect(jest.fn()).toHaveBeenCalledTimes(1)

    Expected mock function to have been called one time, but it was called zero times.

      35 |     await registerUser(user, historyMock);
      36 | 
    > 37 |     expect(mockAxios.post).toHaveBeenCalledTimes(1);

任何想法为什么模拟不起作用?

【问题讨论】:

  • registerUser 返回一个未被调用的函数。
  • 伟大的收获!我在回复中错过了这一点
  • 来自 /__mocks__/axios.js 的 @jonrsharpe 不是返回一个空洞的承诺吗?我假设该过程会执行 POST 调用(返回一个空承诺),然后继续使用 registerUser。
  • 被模拟的方法返回什么并不重要——正如你所看到的,它永远不会被调用。您需要调用从registerUser 返回的函数,并使用经过测试的dispatch。
  • 谢谢,@jonrsharpe!看了代码后,我也注意到registerUser函数返回了包含dispatch作为参数的函数。

标签: reactjs jestjs


【解决方案1】:

正如@jonrsharpe 在 cmets 中指出的那样,registerUser 函数正在返回函数:

dispatch => axios
  .post('/users/register', user)
  .then(() => history.push('/login'))
  .catch((err) => {
    dispatch(handleError(err));
  });

所以为了让它工作,我不得不使用redux-mock-store npm 模块来模拟商店。新的测试代码如下:

import mockAxios from 'axios';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

import { setCurrentUser, registerUser } from '../../actions/auth';
import user from '../fixtures/user';

const defaultStoreState = { errors: {}, auth: { isAuthenticated: false, user: {} } };
const createMockStore = configureMockStore([thunk]);

describe('Register User', () => {
  test('Should call register API and redirect to login', (done) => {
    const mockStore = createMockStore(defaultStoreState);
    const historyMock = { push: jest.fn() };

    mockStore.dispatch(registerUser(user, historyMock)).then(() => {
      expect(mockAxios.post).toHaveBeenCalledTimes(1);
      expect(historyMock.push).toHaveBeenCalledTimes(1);
      expect(historyMock.push).toHaveBeenCalledWith('/login');

      done();
    });
  });
});

现在测试通过了。

【讨论】:

    【解决方案2】:

    我认为您没有正确设置模拟。

    mockAxios.post.mockImplementationOnce
    

    应该改为

    mockAxios.post = jest.fn().mockResolvedValueOnce('bloofblurg');
    

    然后您可以再次检查post 是否已被调用一次并解析了预期值。

    expect(mockAxios.post).resolves.toBe('bloofblurg');
    

    见

    1. https://jestjs.io/docs/en/mock-function-api#mockfnmockresolvedvalueoncevalue
    2. https://jestjs.io/docs/en/expect#resolves

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 2020-01-04
      • 2022-07-21
      • 1970-01-01
      • 1970-01-01
      • 2020-11-06
      • 1970-01-01
      • 2021-12-03
      相关资源
      最近更新 更多