1
votes

I am trying to unit test a function which sends a post request then the API returns a json object. I am trying to do this using jest and fetch-mock-jest.

Now instead of the expected payload the tested function receives {"size":0,"timeout":0} and throws error invalid json response body at reason: Unexpected end of JSON input. Pretty sure there is something basic I don't see. I spent way more time on this without any progress than I'd like to admit.

Edit: I am pretty new to jest and unit testing in general, so if someone has a better suggestion to go about mocking fetch, please tell me.

Test File

import fetchMock from 'fetch-mock-jest'

import {
  refreshAccessToken, isTokenExpired
} from '../../../lib/access/AccessToken'

describe('AccessToken Component...', () => {
it('...Refreshes AccessToken', async () => {
    const responseBody = { accessToken: taiDeveloperTokenValid } // The payload I want the AccessToken.refreshAccessTokento get
    setAccessToken(taiDeveloperTokenExpired)

    process.env.NEXT_PUBLIC_AUTH_API_HTTPS_URL = 'http://new-api.com'
    fetchMock.post(
      `${process.env.NEXT_PUBLIC_AUTH_API_HTTPS_URL}/refreshToken`,
      new Promise((res) =>
        setTimeout(
          () =>
            res({
              status: 200,
              body: JSON.stringify(responseBody),
              statusText: 'OK',
              headers: { 'Content-Type': 'application/json' },
            }),
          50,
        ),
      ),
    )
    const refreshAccessTokenResponse = await refreshAccessToken()
    expect(refreshAccessTokenResponse).toBe(true)
    expect(isTokenExpired()).toBe(false)
  })
  }

Function I am testing

import fetch from 'isomorphic-unfetch'

export const refreshAccessToken = async (): Promise<boolean> => {
  try {
    const response = await fetch(
      `${process.env.NEXT_PUBLIC_AUTH_API_HTTPS_URL}/refreshToken`,
      {
        method: 'POST',
        credentials: 'include',
      },
    )
    console.log(JSON.stringify(await response)) // this prints {"size":0,"timeout":0}
    const data = await response.json()
    accessToken = data.accessToken
    return true
  } catch (error) {
    console.log(error) // this prints  FetchError { message: 'invalid json response body at  reason: Unexpected end of JSON input', type: 'invalid-json'
    return false
  }
}
1

1 Answers

0
votes

You can use jest.mock(moduleName, factory, options) to mock isomorphic-unfetch module by yourself. Don't need fetch-mock-jest module.

E.g.

main.ts:

import fetch from 'isomorphic-unfetch';

export const refreshAccessToken = async (): Promise<boolean> => {
  try {
    const response = await fetch(`${process.env.NEXT_PUBLIC_AUTH_API_HTTPS_URL}/refreshToken`, {
      method: 'POST',
      credentials: 'include',
    });
    const data = await response.json();
    const accessToken = data.accessToken;
    console.log(accessToken);
    return true;
  } catch (error) {
    console.log(error);
    return false;
  }
};

main.test.ts:

import { refreshAccessToken } from './main';
import fetch from 'isomorphic-unfetch';
import { mocked } from 'ts-jest/utils';

jest.mock('isomorphic-unfetch');

const fetchMocked = mocked(fetch);

describe('66009798', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  it('should get access token', async () => {
    process.env.NEXT_PUBLIC_AUTH_API_HTTPS_URL = 'http://new-api.com';
    const data = { accessToken: '123' };
    const mResponse = { json: jest.fn().mockResolvedValueOnce(data) };
    fetchMocked.mockResolvedValueOnce(mResponse as any);
    const actual = await refreshAccessToken();
    expect(actual).toBeTruthy();
    expect(fetch).toBeCalledWith('http://new-api.com/refreshToken', {
      method: 'POST',
      credentials: 'include',
    });
    expect(mResponse.json).toBeCalledTimes(1);
  });
});

unit test result:

 PASS  examples/66009798/main.test.ts (13.604 s)
  66009798
    √ should get access token (37 ms)

  console.log
    123

      at examples/66009798/main.ts:11:13

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files |   83.33 |      100 |     100 |      80 |
 main.ts  |   83.33 |      100 |     100 |      80 | 14-15
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        15.989 s