Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to mock axios response if we use axios-hooks? #35

Closed
LiaoJimmy opened this issue Sep 29, 2019 · 8 comments
Closed

How to mock axios response if we use axios-hooks? #35

LiaoJimmy opened this issue Sep 29, 2019 · 8 comments

Comments

@LiaoJimmy
Copy link

LiaoJimmy commented Sep 29, 2019

Hello, I try to mock axios response by:
@react-mock/xhr: https://github.com/ctimmerm/axios-mock-adapter
axios-mock-adapter: https://github.com/ctimmerm/axios-mock-adapter
and enve jest mock: https://jestjs.io/docs/en/mock-functions#mocking-modules
They all mock axios response failed.

Do you have any example to mock axios if we use axios-hooks?

My example code:

// AxiosHooks.jsx
import React from 'react';
import useAxios from 'axios-hooks';

export default () => {
  const [{ data: getData, loading: getLoading, error: getError }] = useAxios(
    'bins/820fc',
  );

  const [
    { data: putData, loading: putLoading, error: putError },
    executePut,
  ] = useAxios(
    { url: 'bins/820fc', method: 'PUT' },
    { manual: true },
  );

  function updateData() {
    executePut({
      data: {
        ...getData,
        updatedAt: new Date().toISOString(),
      },
    });
  }

  if (getLoading || putLoading) return <p>Loading...</p>;
  if (getError || putError) return <p>Error!</p>;

  return (
    <div>
      <button type="button" onClick={updateData}>update data</button>
      <pre>{JSON.stringify(putData || getData, null, 2)}</pre>
    </div>
  );
};

And here is the test file.

import React from 'react';
import { render, waitForElement, fireEvent } from '@testing-library/react';
import axios from 'axios';
import MockAxios from 'axios-mock-adapter';

import AxiosHooks from './AxiosHooks';

const mock = new MockAxios(axios);

describe.skip('<AxiosHooks />', () => {
  it('should get server time', async () => {
    mock.onGet('/bins/820fc').reply(200, {
      updatedAt: '2019-09-29T04:46:23.256Z',
    });
    const { getByText } = render(<AxiosHooks />);

  // Failed! It will get now time.
    await waitForElement(() => getByText('2019-09-29T04:46:23.256Z'));
  });

  it('should get updated server time', async () => {
    mock.onGet('/bins/820fc').reply(200, {
      updatedAt: '2019-09-29T04:46:23.256Z',
    });
    mock.onPut('/bins/820fc').reply(200, {
      updatedAt: '2019-09-29T04:46:30.256Z',
    });
    const { getByText } = render(<AxiosHooks />);
    const updateButton = await waitForElement(() => getByText('update data'));

    fireEvent.click(updateButton);

    // Failed! It will get now time.
    await waitForElement(() => getByText('2019-09-29T04:46:30.256Z'));
  });
});
@simoneb
Copy link
Owner

simoneb commented Sep 30, 2019

If you're using this library don't mock axios, mock this library via jest

@LiaoJimmy
Copy link
Author

Thanks. I'll try to mock axios-hooks response array.

@lmiguelvargasf
Copy link

@LiaoJimmy , how does your code looks after mocking axios-hooks response?

@LiaoJimmy
Copy link
Author

@LiaoJimmy , how does your code looks after mocking axios-hooks response?

I think mock axios-hooks response is not a good solution.
For mock API response, we have better choice like Mirage JS (https://miragejs.com/).
It has many features and better developer experience.

@simoneb
Copy link
Owner

simoneb commented Apr 25, 2020

@LiaoJimmy @lmiguelvargasf @tgfischer mocking this library with jest is as easy as:

import useAxios from 'axios-hooks'

jest.mock('axios-hooks')

// in your test
useAxios.mockReturnValue([{ data: { ... } }])

@KristianLonergan
Copy link

@simoneb how would you go about mocking axios-hooks when you have multiple instances of useAxios within a file?
For example:

const [{ data: booksData, loading: booksLoading }] = useAxios('/books');
const [{ data: addBookData, loading: addBookLoading }] = useAxios({url: '/addBook', method: 'POST'}, {manual: true});

@simoneb
Copy link
Owner

simoneb commented May 8, 2020

@KristianLonergan in the same way as you would mock a function which is called multiple times, see here.

I appreciate this is not ideal so I'll be looking into #218 that's been opened a few days ago. But, there are ways to mock this easily already.

@dkershner6
Copy link

Just to throw out there, and it is not mutally exclusive with #218 ...

I really appreciate this library, and I had some more complicated mocking scenarios that required several useAxios hooks to be used with each other, relying on one another. The ordered mocking method above falls down when firing off items in random order and such.

So, I created a library to handle every scenario I (and the rest of my company) needed, and you all are free to use it as well: https://www.npmjs.com/package/axios-hooks-mock

It's an implementation that should work well for both simple and complex scenarios and abstracts most of the testing boilerplate away.

Tagging @simoneb just to let him know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants