fetch-mock: log statement interferes with resolution/failure of simple fetch result

476 Views Asked by At

When I write the following code, Jest.js passes the test:

  test("internalFetch()", async () => {
    fetchMock.mock("*", Promise.resolve(JSON.stringify({key1 : "val1"})));
    const response = await fetch('http://starMatcher.com', {
      method : "post"
      , headers : { "content-type" : "application/json" }
    });

    // the next line fails the test when uncommented
    // console.log(await response.json(), `=====response.json()=====`);

    await expect(response.json()).resolves.toStrictEqual({key1 : "val1"});
  });

Uncommenting the log statement instantly breaks the test and displays this in the terminal.

    ✕ internalFetch() (56ms)

    expect(received).resolves.toStrictEqual()

    Received promise rejected instead of resolved
    Rejected to value: [TypeError: body used already for: http://starmatcher.com/]

      191 |     console.log(await response.json(), `=====response.json()=====`);
      192 |     
    > 193 |     await expect(response.json()).resolves.toStrictEqual({key1 : "val1"});
          |           ^
      194 |   });
      195 |   
      196 |   

      at expect (node_modules/expect/build/index.js:138:15)
      at functions/src/classes/__tests__/ScriptTag.test.ts:193:11
      at step (functions/src/classes/__tests__/ScriptTag.test.ts:46:23)
      at Object.next (functions/src/classes/__tests__/ScriptTag.test.ts:27:53)
      at fulfilled (functions/src/classes/__tests__/ScriptTag.test.ts:18:58)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 skipped, 9 passed, 11 total

Anyone know why the log statement is interfering and causing the promise to reject on the (now) 2nd lookup of response?

Also tried

  • Switching fetchMock.post() to use .mock() instead.

Same terminal error.

  • Removing the 2nd .json() execution and switching the matcher to not-strict
  test("internalFetch()", async () => {

    fetchMock.mock("*", Promise.resolve(JSON.stringify({key1 : "val1"})));
    const response = await fetch('http://starMatcher.com', {
      method : "post"
      , headers : {
        "content-type" : "application/json"
      }
    });

    console.log(await response.json(), `=====response.json()=====`);

    await expect(response).toEqual({key1 : "val1"});
  });

// terminal
internalFetch()

    expect(received).toEqual(expected) // deep equality

    - Expected
    + Received

    - Object {
    -   "key1": "val1",
    + Response {
    +   "size": 0,
    +   "timeout": 0,
    +   Symbol(Body internals): Object {
    +     "body": Object {
    +       "data": Array [
    +         123,
    +         34,
    +         107,
    +         101,
    +         121,
    +         49,
    +         34,
    +         58,
    +         34,
    +         118,
    +         97,
    +         108,
    +         49,
    +         34,
    +         125,
    +       ],
    +       "type": "Buffer",
    +     },
    +     "disturbed": true,
    +     "error": null,
    +   },
    +   Symbol(Response internals): Object {
    +     "counter": undefined,
    +     "headers": Headers {
    +       Symbol(map): Object {
    +         "Content-Length": Array [
    +           "15",
    +         ],
    +         "Content-Type": Array [
    +           "text/plain;charset=UTF-8",
    +         ],
    +       },
    +     },
    +     "status": 200,
    +     "statusText": "OK",
    +     "url": "http://starmatcher.com/",
    +   },
      }

      191 |     console.log(await response.json(), `=====response.json()=====`);
      192 |     
    > 193 |     await expect(response).toEqual({key1 : "val1"});
          |                            ^
      194 |   });
      195 |   
      196 |   

      at functions/src/classes/__tests__/ScriptTag.test.ts:193:28
      at step (functions/src/classes/__tests__/ScriptTag.test.ts:46:23)
      at Object.next (functions/src/classes/__tests__/ScriptTag.test.ts:27:53)
      at fulfilled (functions/src/classes/__tests__/ScriptTag.test.ts:18:58)

  console.log functions/src/classes/__tests__/ScriptTag.test.ts:191
    { key1: 'val1' } =====response.json()=====

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 skipped, 9 passed, 11 total


  • Previous example but adding back .json() on the final line:
    await expect(response.json()).toEqual({key1 : "val1"});


// terminal
expect(received).toEqual(expected) // deep equality

    - Expected
    + Received

    - Object {
    -   "key1": "val1",
    - }
    + Promise {}

1

There are 1 best solutions below

0
On

Solved with 2 changes:

  1. Import isomorphic-fetch in the target file (not the test file, which imports node-fetch) without a namespace:

import "isomorphic-fetch";

  1. Remove Promise.resolve in the 2nd argument of fetchMock.mock() (or the other mock methods such as .getOnce())
  fetchMock.getOnce("*", {fetchMockKey: "fetchMockVal"});
  const scriptTagTester = new ScriptTagTester("", "", "x.js");

  const result = await scriptTagTester.internalFetch();
  const json = await result.json();
  expect(json).toEqual({fetchMockKey : 'fetchMockVal'});