6

I have a custom hook called useFetch which simply fetches data and returns it, in my component test I want to just mock this hook to return some fake data, how can I go about doing this?

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

export const useFetch = (url: string) => {
  const [data, setData] = useState();

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url);
        const json = await res.json();
        setData(json);
      } catch (error) {
        console.log(error);
      }
    };

    fetchData();
  }, [url]);

  return data;
};

const App = () => {
  const config = useFetch(`/api/url`);

  return (
    <div></div>
  );
};

export default App;

Is there anyway I can mock useFetch so that const config is set to some dummy data in my Jest test?

halfer
  • 19,824
  • 17
  • 99
  • 186
offlineanton
  • 71
  • 1
  • 4
  • Does this answer your question? [How can I mock fetch function in Node.js by Jest?](https://stackoverflow.com/questions/53484219/how-can-i-mock-fetch-function-in-node-js-by-jest) – j3ff May 01 '20 at 12:36
  • Not really as that seems to be mocking the fetch function, as really I just want to mock the hook return. – offlineanton May 01 '20 at 12:46
  • IMHO you should'nt mock the hook, because the code inside it wouldn't be covered by your test. Mocking the fetch call is the better option so that your test also cover the implementation of the hook and therefore be sure there is no mistake or unwanted behavior. – j3ff May 01 '20 at 12:48

2 Answers2

2

I Will suggest to put your hook in separate file lets say useFetch.js conntains

import { useEffect, useState } from "react";

export const useFetch = (url: string) => {
  const [data, setData] = useState();

  useEffect(() => {
    const fetchData = async () => {
      try {
        const res = await fetch(url);
        const json = await res.json();
        setData(json);
      } catch (error) {
        console.log(error);
      }
    };

    fetchData();
  }, [url]);

  return data;
};

Keeping your app component file like follows

import React from "react";

import { useFetch } from "./useFetch";


const App = () => {
  const config = useFetch(`/api/url`);

  return (
    <div></div>
  );
};

export default App;

with above split you can easily mock your hook, example test file as follows

import React from "react";
import { render } from "@testing-library/react";
import App from "./App";


// mock config
const mockConfig = {
    data: "mock data"
};

// this will mock complete file, we have provided mock implementation
// for useFetch function
jest.mock("./useFetch", () => ({
    useFetch: () => mockConfig
}));

test("should render with mock useFetch", () => {
    const { getByText } = render(<App />);
    // test logic goes here
});


Assuming all the files are in same directory.

Ajhar Shaikh
  • 1,106
  • 2
  • 14
  • 33
0

You could try to mock the fetch library.

In the test setup:

global.fetch = jest.fn()

And then in your test:

global.fetch.mockResolvedValue({ json: () => ({ data: "" })})
froston
  • 1,027
  • 1
  • 12
  • 24