Home > Back-end >  How can I test react component that fetches the data from firestore?
How can I test react component that fetches the data from firestore?

Time:03-30

I have been told that we should be using mock data and not interact with our real database resources.

I also been told that I should "Mock firebase object and return fake results from it", but where do I mock the firebase object, is it my actual component or is it in my test file and how do I actually mock it?

here is the code that I have:

// just a hook that fetches current user data

export const useGetCurrentUsersProfile = () => {
  const userInfoRef = doc(firestore, "users", auth.currentUser?.uid ?? "_STUB_");
  return useFirestoreDocument(
    ["userInfo"],
    userInfoRef,
    {
      subscribe: false,
    },
    {
      select: (data) => {
        const currentUsersProfile = data.data() as UserInfo;
        return currentUsersProfile;
      },
      enabled: !!auth.currentUser?.uid,
    }
  );
};

My react component that uses that hook to fetch data:

import React from "react";
import { useGetCurrentUsersProfile } from "../app/utilityfunctions";

function Siuu() {
  const { data: currentUser } = useGetCurrentUsersProfile();
  return (
    <div>
      <div>{currentUser?.name}</div>
    </div>
  );
}

export default Siuu;
/** @jest-environment jsdom */

import { render, screen } from "@testing-library/react";
import Siuu from "./siuu";

test("renders component", () => {
  render(<Siuu />);
  const randomElement = screen.getByText(/Jack/i);
  expect(randomElement).toBeInTheDocument();
});

Where and how do I mock it, if I just wanted to return this data from my hook:

{name:"jack", email:"[email protected]"}

CodePudding user response:

Mocking is done in the test code, not in the real app code.

What it means is: you create a fake version of a thing, so that the real thing doesn't get used when the test makes the app do stuff. Jest has tools that help you do this.

In your case, it seems like the thing you should mock is the doc and/or useFirestoreDocument functions. Your code sample doesn't say where those two things come from, and I don't know firestore, so I'll just assume that both are imported from a single "some-firestore-pkg" package like so: import { doc, useFirestoreDocument } from 'some-firestore-pkg'

The simplest way would be to create a one-off mock for this test specifically, but if this firestore stuff is used through the app and you want to write tests for the rest, you'll want to read up on the tools and patterns that Jest provides for creating reusable mocks. For this answer, I'll do it all with one-off mocks.

/*
    STEP 1: Import some-firestore-pkg package so we can manipulate it during the
    tests. This will be the real firestore package.
*/
import firestorePkg from 'some-firestore-pkg'

// ...skipping down to your test

test("renders component", () => {
    /*
        STEP 2: replace the real `doc` function with a fake version that returns a
        hard-coded value.
        
        We MUST replace it to prevent the real one from doing any real work,
        although we may not need to make the fake version return anything. But,
        let's do so, in order to miminize the chance that this test will stop
        working when the hook is modified in the future to verify the results of
        each operation.
    */
    let docSpy = jest.spyOn(firestorePkg, 'doc').mockReturnValue(
        'A_FAKE_USER_INFO_REF'
    )
    // now, when the real hook calls the doc(...) function, it will get that value
    
    /*
        STEP 3: replace the real useFirestoreDocument with a fake version that
        returns the hard-coded fake data that you want the app to receive during the
        test. You can probably guess what this will look like:
    */
    let useDocSpy = jest.spyOn(firestorePkg, 'useFirestoreDocument').mockReturnValue(
        { data: { name: "jack", email: "[email protected]" } }
    )
    
    /*
        STEP 4: now that we've "arranged," let's "act" and then "assert"
    */
    let app = render(<Siuu />)
    let randomElement = app.getByText(/Jack/i)
    expect(randomElement).toBeInTheDocument()
    
    // STEP 5: completely remove our fake versions so other tests aren't impacted
    docSpy.mockRestore()
    useDocSpy.mockRestore()
})
  • Related