首页 > 解决方案 > 为每个测试获取新的功能实例

问题描述

我在一个文件中有一些测试,

我用一些案例检查我的减速器

我的代码看起来像这样

my code

import axiosInstance from '~/utils/network';
const fetcher = axiosInstance();


const fetchMiddleware = () => {
  switch (type) {

     case 'LOGOUT':{
      try {
          await fetcher.get(API.GET.LOGOUT_OPERATION);

          dispatch({ type: 'LOGOUT_SUCCESS' });
        } catch (err) {
          dispatch({ type: 'LOGOUT_FAIL' });
        }
      });
     }
   }
}

my test


import axiosInstance from '../../src/utils/network';

import configureStore from 'redux-mock-store';

const middlewares = [fetchMiddleware, thunk];
const mockStore = configureStore(middlewares);
const store = mockStore(getInitialReducerState());


jest.mock('../../src/utils/network', () => {
  const axiosInstance = jest.fn().mockImplementation(() => {
    return {
      get: jest.fn().mockImplementation(() => {
        return {
          headers: {},
        };
      }),
    };
  }) as any;
  axiosInstance.configure = jest.fn();
  return axiosInstance;
});


describe('test LOGOUT', () => {
  beforeEach(() => {
    store.clearActions();
  });

  it('should test be success', async () => {
    await store.dispatch({
      type: 'LOGOUT',
      payload: { userName: 'testUserName' },
    });

    expect(store.getActions()).toContainEqual({
      type: 'LOGOUT_SUCCESS',
    });
  });

  it('should test be fail', async () => {
    (axiosInstance as jest.Mock).mockImplementation(() => {
      return {
        get: jest.fn().mockImplementation(() => {
          throw new Error(' ');
        }),
      };
    });
    await store.dispatch({
      type: 'LOGOUT',
      payload: { userName: 'testUserName' },
    });

    expect(store.getActions()).toContainEqual({
      type: 'LOGOUT_FAIL',
    });
  });
});

我想测试两种情况:成功和失败,

我嘲笑这个axiosInstance功能。

但即使我在第二个测试中覆盖了模拟,我也得到了第一个模拟,因为我的代码只加载axiosInstance了一次。

我能做些什么?

标签: javascriptreactjsunit-testingtestingjestjs

解决方案


最好使用现有的库来模拟 Axios,它可以避免样板代码和模拟实现中的潜在错误;moxios已经被建议了。

每次测试都模拟很不方便,axiosInstance因为它已经在导入测试模块时被调用,所以这需要每次测试重新导入它;另一个答案解释了它是如何完成的jest.isolateModules

由于axiosInstance只评估一次并且应该返回模拟对象,因此每次测试模拟一次然后更改实现很方便:

jest.mock('~/utils/network', () => {
  const axiosMock = { get: jest.fn(), ... };
  return {
    axiosInstance: () => axiosMock;
  };
});

const axiosMock = axiosInstance();

...

(axiosMock.get axiosInstance as jest.Mock).mockImplementation(() => {
  throw new Error(' ');
});

await store.dispatch(...);

这需要使用jest.restoreAllMocksinbeforeEach或类似的 Jest 配置选项来避免测试交叉污染。

请注意,Axios 不会抛出错误而是返回被拒绝的 Promise,这可能会影响测试结果,请参阅有关库的好处的注释。


推荐阅读