jefflau / jest-fetch-mock

Jest mock for fetch
MIT License
883 stars 116 forks source link

jest.toHaveBeenCalledTimes() doesn't count all API call #130

Open edouard-lopez opened 5 years ago

edouard-lopez commented 5 years ago

I'm trying to test a method to ensure all API calls are correctly done.

However only the first one seem to be log and available in fetch.mock.calls and toHaveBeenCalledTimes:

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

Error

  ● Outcall Service › addExtensions › should create and associate extension to outcall

    expect(jest.fn()).toHaveBeenCalledTimes(3)

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

      42 |       expect(fetch).toHaveBeenCalled();
      43 |       console.log('fetch.mock.calls', fetch.mock.calls);
    > 44 |       expect(fetch).toHaveBeenCalledTimes(3);
         |                     ^
      45 |       expect(fetch.mock.calls[0][0]).toBe('https://undefined/api/confd/1.1/contexts/1');
      46 |       expect(fetch.mock.calls[1][0]).toBe('https://undefined/api/confd/1.1/extension/');
      47 |       expect(fetch.mock.calls[0][0]).toBe('https://undefined/api/confd/1.1/outcalls/3/extensions/1');

      at Object.toHaveBeenCalledTimes (src/pbx/outcalls/__tests__/services.test.js:44:21)

Console.log

Mock respond correctly to the calls

  console.log src/pbx/outcalls/__tests__/services.test.js:43
    fetch.mock.calls [ [ 'https://undefined/api/confd/1.1/contexts/1',
        { method: 'GET', headers: [Headers] } ] ]

  console.log src/pbx/outcalls/services.js:10
    context { id: 1, name: 'selected-context' }

  console.log src/pbx/outcalls/services.js:12
    newExtension { id: 2, context: 'selected-context', exten: '*123' }

Test

const mockJsonResponseOnce = body =>
  fetch.mockResponseOnce(JSON.stringify(body), { headers: { 'Content-Type': 'application/json' } });

it('should create and associate extension to outcall', async () => {
      fetch.resetMocks();

      mockJsonResponseOnce({ id: 1, name: 'selected-context' }); // fetched context
      mockJsonResponseOnce({ id: 2, context: 'selected-context', exten: '*123' }); // created extension
      mockJsonResponseOnce({}); // association outcall-extension

      const foo = await Outcall.addExtensions({ id: 3 }, { extensions: [{ context_id: 1, exten: '*123' }] });

      expect(fetch).toHaveBeenCalled();
      expect(fetch).toHaveBeenCalledTimes(3);  // <--- FAIL HERE
      expect(fetch.mock.calls[0][0]).toBe('https://undefined/api/confd/1.1/contexts/1');
      expect(fetch.mock.calls[1][0]).toBe('https://undefined/api/confd/1.1/extension/');
      expect(fetch.mock.calls[0][0]).toBe('https://undefined/api/confd/1.1/outcalls/3/extensions/1');
    });

Code

const addExtensions = async (outcall, formData) => {
  const { extensions } = formData;
  await extensions.forEach(async extension => {
    const context = await Context.read(extension.context_id);
    console.log('context', context);
    const newExtension = await Extension.create({ context: context.name, exten: extension.exten });
    console.log('newExtension', newExtension);
    await associate({ name: 'outcalls', id: outcall.id }, { name: 'extensions', id: newExtension.id });
  });
};

Is it the expected behavoir?

jefflau commented 4 years ago

No that's definitely not expected behaviour. The only thing I can think of without investigating is that you are only calling fetch once. But you are also showing the logs from your calls

edouard-lopez commented 4 years ago

Below is how I setup jest-fetch-mock in src/setupTests.js

import fetch from 'jest-fetch-mock';

jest.setMock('isomorphic-fetch', fetch);

It's also imported at the top of my test file src/pbx/outcalls/__tests__/services.test.js and reset mock before each tests:

import fetch from 'jest-fetch-mock';

import * as Outcall from '../services';

describe('Outcall Service', () => {
  beforeEach(() => {
    localStorage.setItem('connectedInstance', JSON.stringify({ connectedInstance: 'fake' }));
    fetch.resetMocks();
  });