using axios-mock-adapter to test API call in use effect

2.9k Views Asked by At

I've been working through this problem for a couple days and believe I am close to a solution. I am trying to mock an API call which is triggered in my useEffect

  useEffect(() => {
    getAdminOrg();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const getAdminOrg = () => {
    const token = localStorage.getItem("token");
    const URL = `organizations/organizations/`;
    let config = {
      headers: { Authorization: "JWT " + token }
    };
    axios
      .get(URL, config)
      .then(response => {
        setOrgTitle(response.data.name);
      })
      .catch(error => {
        if (error.response) {
          console.log(error.response);
          if (error.response.status === 401) {
            props.renewToken();
          }
        }
      });
  };

If the setOrgTitle hook runs I will be able to detect this by a change to a text field. I am trying to test this here:

it("mocks API call", done => {
  const wrapper = mount(
    <OrganizationDocs />
  );
  const mock = new MockAdapter(axios);
  mock
    .onGet(`organizations/organizations/`, {
      headers: { Authorization: "JWT1111" }
    })
    .reply(200, response.data);

  setImmediate(() => {
    wrapper.update();
    expect(findByTestId(wrapper, "org-docs-header").text()).toContain(
      organizationsOrganizations[0].name
    );
    done();
  });
});

I am getting unhandled promise rejection warnings when I run my tests. Also when I try to console log the wrapper I can see that the API call is not using the test header that I am applying so I am pretty certain the API call is not using my mock.

Any help would be appreciated.

1

There are 1 best solutions below

0
On

Here is the unit test solution only using jestjs + enzyme + react-dom/test-utils.

E.g.

index.ts:

import React, { useEffect, useState } from 'react';
import axios from 'axios';

export const OrganizationDocs = (props) => {
  const [orgTitle, setOrgTitle] = useState('');

  useEffect(() => {
    getAdminOrg();
  }, []);

  const getAdminOrg = () => {
    const token = localStorage.getItem('token');
    const URL = `organizations/organizations/`;
    let config = {
      headers: { Authorization: 'JWT ' + token },
    };
    axios
      .get(URL, config)
      .then((response) => {
        setOrgTitle(response.data.name);
      })
      .catch((error) => {
        if (error.response) {
          console.log(error.response);
          if (error.response.status === 401) {
            props.renewToken();
          }
        }
      });
  };

  return <div className="org-docs-header">orgTitle: {orgTitle}</div>;
};

index.spec.ts:

import React from 'react';
import { OrganizationDocs } from '.';
import { mount } from 'enzyme';
import axios from 'axios';
import { act } from 'react-dom/test-utils';

const mLocalStorage = {
  _storage: {},
  getItem: jest.fn((key) => {
    return mLocalStorage._storage[key];
  }),
  setItem: jest.fn((key, value) => {
    mLocalStorage._storage[key] = value;
  }),
};
Object.defineProperty(window, 'localStorage', {
  value: mLocalStorage,
});

describe('MyComponent', () => {
  afterEach(() => {
    jest.restoreAllMocks();
    jest.resetAllMocks();
  });
  it('mocks API call', async () => {
    const token = 'JWT1111';
    mLocalStorage.setItem('token', token);
    const response = { data: { name: 'mocked name' } };
    jest.spyOn(axios, 'get').mockResolvedValueOnce(response);
    const wrapper = mount(<OrganizationDocs />);
    await act(async () => {
      await new Promise((resolve) => setTimeout(resolve, 0));
    });
    expect(wrapper.find('.org-docs-header').text()).toContain('mocked name');
    expect(axios.get).toBeCalledWith('organizations/organizations/', {
      headers: { Authorization: 'JWT ' + token },
    });
  });
});

Unit test result with coverage report:

 PASS  src/stackoverflow/59379085/index.spec.tsx (9.958s)
  MyComponent
    ✓ mocks API call (85ms)

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |    78.95 |        0 |       80 |    76.47 |                   |
 index.tsx |    78.95 |        0 |       80 |    76.47 |       23,24,25,26 |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.427s

Source code: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59379085