简体   繁体   English

如何注入多个模拟承诺以对 JS 中的 fetch 进行单元测试?

[英]How to Inject multiple mock promises to unit test the fetch in JS?

I'm trying to setup unit tests for the api calls in my JS project.我正在尝试为我的 JS 项目中的 api 调用设置单元测试。 Able to set it up for a single API call, using the following format能够为单个 API 调用设置它,使用以下格式

describe('Token refresh success', () => {
  beforeAll(() => {
    global.fetch = () =>
      Promise.resolve({
        json: () => Promise.resolve(mockTokenCreateSuccess),
      })
  })

  afterAll(() => {
    global.fetch = unmockedFetch
  })

  test('testTokenRefreshSuccess', async () => {
    const tokenData = await c.tokenRefresh();
    expect(tokenData.access_token).toEqual('SYoHdm4yw');
    expect(tokenData.refresh_token).toEqual('QxJ3yEgX4NThbTE66u7lshWTpQkRBilq');
  });
})

Now this format works great, and I can create individual tests by injecting one promise.现在这种格式效果很好,我可以通过注入一个 promise 来创建单独的测试。

Now, there is a case I want to unit test where a particular API call is made twice.现在,有一个案例我想对特定的 API 调用进行两次单元测试。 I need to inject fail response the first time, and success response the second time.我需要第一次注入失败响应,第二次注入成功响应。

I tried the following approach, but did not work:我尝试了以下方法,但没有奏效:

describe('Token refresh trigger as expected on create token fail', () => {
  beforeAll(() => {
    global.fetch = () => [
      Promise.resolve({
        json: () => Promise.reject(mockError(400)),
      }),
      Promise.resolve({
        json: () => Promise.resolve(mockTokenCreateSuccess),
      })
    ] 
  })

  afterAll(() => {
    global.fetch = unmockedFetch
  })

  test('testTokenRefreshTriggerOnTokenCreateFail', async () => {
    const tokenData = await c.tokenRefresh();
    expect(tokenData.access_token).toEqual('jkhjk');
    expect(tokenData.refresh_token).toEqual('dfdfdf');
  });
})

and my tokenRefresh() function is supposed to get called 2 times if it gets 400 error.如果出现 400 错误,我的 tokenRefresh() function 应该被调用 2 次。

async tokenRefresh(retryCount = 0) {
        console.log('tokenRefresh');

        const request = this.getTokenRefreshRequest();
        try {
            const response = await this.fetchData(request);
            console.log('token refresh success', response);
            return { access_token, refresh_token };
        } catch (err) {
            if ((err.status == 400 || err.status == 401) && retryCount < 2) {
                await this.tokenRefresh(retryCount++);
            } else {
                throw new Error(`unable to refresh a token from API ${err.status}`);
            }
        }
    };

I'm able to verify that by using single promise我可以通过使用单个 promise 来验证

  Promise.resolve({
    json: () => Promise.reject(mockError(400)),
  })

the tokenRefresh() gets called again as expected, but in the second time I could not figure out how to pass the success promise, at the moment it fails the second time too. tokenRefresh() 按预期再次被调用,但第二次我无法弄清楚如何通过成功 promise,目前它第二次也失败了。

I was able to find a working combination我能够找到一个有效的组合

beforeAll(() => {
    global.fetch = fetchMock.mockRejectOnce(customError) // makes sure first api call fails
    .mockResponseOnce(JSON.stringify(successResponse)) // makes sure second api call succeeds
  })

This made my test pass这使我的测试通过

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM