开玩笑:如何模拟同一文件上的承诺以获取解决和拒绝选项?

Non*_*Non 5 javascript testing unit-testing reactjs 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);
  })
}));
Run Code Online (Sandbox Code Playgroud)

那么唯一通过的测试将是最后宣布的测试。在上述情况下,这种reject情况将通过并且第一个模拟将被忽略。

这是我的整个测试:

// @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();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

现在的情况是,通过的测试是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);
  })
}));
Run Code Online (Sandbox Code Playgroud)

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 }))
}));
Run Code Online (Sandbox Code Playgroud)

那么测试将通过should call callbacks consequently,那么我该怎么做才能模拟拒绝和解决而不干扰另一个呢?

chr*_*r85 10

我在寻找一个好的实践来做到这一点时遇到了这个问题,因为我遇到了同样的问题,但我找到了一种解决方法来使其发挥作用。尽管我认为您已经解决了这个问题,但我将在这里为未来的读者留下我的临时解决方案。

基本上,我在我想拒绝承诺的测试中重写了该方法的模拟实现。

因此,我将在声明之前删除拒绝实现,并通过以下方式describe将其添加到测试中:'should handle error'

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

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

// @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();
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

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

我将继续寻找更聪明的解决方案。