javascript - Jest : How to mock a promise on the same file for resolve and reject options?

标签 javascript reactjs unit-testing testing jestjs

所以我试图测试我的实现的积极和消极方面。如果我这样做:

jest.mock('./apiClient', () => ({
  get: jest.fn((url: string) => Promise.resolve({ data: mockData }))
}));

jest.mock('./apiClient', () => ({
  get: jest.fn().mockImplementation((url: string) => {
    console.log('error result');
    return Promise.reject(mockError);
  })
}));

然后唯一通过的测试将是最后一个声明的。在上述情况下,reject 情况将通过,第一个 mock 将被忽略。

这是我的整个测试:

// @ts-ignore
import ApiClient from './apiClient';
import ApiService from './apiService';

const mockData = {};
const mockError = { message: 'Smth Bad Happened' };

const firstCallback = jest.fn((data: any) => data);
const secondCallback = jest.fn((data: any) => data);

jest.mock('./apiClient', () => ({
  get: jest.fn((url: string) => Promise.resolve({ data: mockData }))
}));

jest.mock('./apiClient', () => ({
  get: jest.fn().mockImplementation((url: string) => {
    console.log('error result');
    return Promise.reject(mockError);
  })
}));

describe('apiService', () => {
  it('should call callbacks consequently', done => {
    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(1);
      expect(firstCallback).toBeCalledWith(mockData);

      expect(secondCallback).toBeCalledTimes(1);
      expect(secondCallback).toBeCalledWith(firstCallback(mockData));
      done();
    });
  });

  it('should handle error', done => {
    console.error = jest.fn();
    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(0);
      expect(secondCallback).toBeCalledTimes(0);
      expect(console.error).toBeCalledTimes(1);
      expect(console.error).toBeCalledWith('ApiClient testUrl', mockError);
      done();
    });
  });
});

就目前而言,测试通过是 should handle error 这是第二个,但是如果我从

切换位置
jest.mock('./apiClient', () => ({
  get: jest.fn((url: string) => Promise.resolve({ data: mockData }))
}));

jest.mock('./apiClient', () => ({
  get: jest.fn().mockImplementation((url: string) => {
    console.log('error result');
    return Promise.reject(mockError);
  })
}));

jest.mock('./apiClient', () => ({
  get: jest.fn().mockImplementation((url: string) => {
    console.log('error result');
    return Promise.reject(mockError);
  })
}));

jest.mock('./apiClient', () => ({
  get: jest.fn((url: string) => Promise.resolve({ data: mockData }))
}));

然后测试通过将是应该调用回调,那么我可以做些什么来模拟 reject 和 resolve 而不会相互干扰?

最佳答案

我在寻找一个好的做法时遇到了这个问题,因为我遇到了同样的问题,但我找到了解决方法来解决这个问题。尽管我想您已经解决了这个问题,但我还是将我的临时解决方案留在这里供 future 的读者使用。

基本上,我在我想拒绝 promise 的测试中覆盖了该方法的模拟实现。

所以我会去掉 describe 声明之前的 reject 实现,并将其添加到 'should handle error' 测试中方式:

ApiClient.get: jest.fn().mockImplementation((url: string) => {
    console.log('error result');
    return Promise.reject(mockError);
})

您的最终测试将如下所示:

// @ts-ignore
import ApiClient from './apiClient';
import ApiService from './apiService';

const mockData = {};
const mockError = { message: 'Smth Bad Happened' };

const firstCallback = jest.fn((data: any) => data);
const secondCallback = jest.fn((data: any) => data);

jest.mock('./apiClient', () => ({
  get: jest.fn((url: string) => Promise.resolve({ data: mockData }))
}));

describe('apiService', () => {
  it('should call callbacks consequently', done => {
    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(1);
      expect(firstCallback).toBeCalledWith(mockData);

      expect(secondCallback).toBeCalledTimes(1);
      expect(secondCallback).toBeCalledWith(firstCallback(mockData));
      done();
    });
  });

  it('should handle error', done => {
    ApiClient.get: jest.fn().mockImplementation((url: string) => {
        console.log('error result');
        return Promise.reject(mockError);
    });
    console.error = jest.fn();
    ApiService.makeApiCall('testUrl', firstCallback, secondCallback).then(() => {
      expect(firstCallback).toBeCalledTimes(0);
      expect(secondCallback).toBeCalledTimes(0);
      expect(console.error).toBeCalledTimes(1);
      expect(console.error).toBeCalledWith('ApiClient testUrl', mockError);
      done();
    });
  });
});

我认为这不是最好的方法,但一点也不差,应该适用于这个例子。

我会继续寻找更智能的解决方案。

关于javascript - Jest : How to mock a promise on the same file for resolve and reject options?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57704755/

相关文章:

java - 如何对使用 Java UUID 的代码进行单元测试?

javascript - 使用客户端脚本的交互式 map

javascript - 如何在 Javascript 中创建真正的模态警报/确认?

reactjs - 使用服务器配置react-router

reactjs - 如何使用 Material UI 在应用栏下方打开下拉菜单?

visual-studio-2010 - 如何在 TFS 下以 Release 模式禁用单元测试

javascript - 可靠的 html5 输入类型处理

javascript - 我的问题是关于 material-ui 4,不存在的 "mask"属性的 material-ui/pickers compaining

javascript - 在父组件 React 中显示按钮信息

Python 单元测试 : In Nose is there a way to skip a test case from nose. run()?