-1

I don't seem to find a solution for the below code / test to work (I went through a lot of articles and stackOverflow...). Various solutions provided by chatGPT are useless as well. I also see people telling that you should never mock hooks. So my question is: should I just forget it because it's not the best practice anyway?

P.S. This code is from the course I am following at Zero to Mastery, however, I am using Vite with Vitest instead of Create-React-App and Jest which are used in the course. In this particular lesson teacher was showing the workaround when sagas are involved, and that's why the idea is to spy on useDispatch instead of using fire.Event + store.getState....

test('it should dispatch signOutStart action when clicking on Sign Out link', async () => {

    const mockDispatch = vi.fn();
    vi.spyOn(reactRedux, 'useDispatch').mockReturnValue(mockDispatch);
    
    renderWithProviders(<Navigation />, {
      preloadedState: {
        user: {
          currentUser: {} 
        }
      }
    });

    const signOutLinkElement = screen.getByText(/sign out/i);
    expect(signOutLinkElement).toBeInTheDocument();

    await fireEvent.click(signOutLinkElement);
    expect(mockDispatch).toHaveBeenCalled(); 
    expect(mockDispatch).toHaveBeenCalledWith(signOutStart());

    mockDispatch.mockClear();
  })
8
  • "should I just forget it because it's not the best practice anyway?" - Basically, yes. dispatch is an internal implementation detail. You are already rendering the component-under-test within a Redux provider, so why not just assert that the signOutStart function was called? It's the code you technically own, right? Commented Apr 6 at 16:31
  • signOutStart is just the user action that kicks off the saga which I guess makes it quite complicated to test, and that's why the teacher of the course was proposing the spying on useDispatch only. Commented Apr 6 at 19:54
  • There isn't much that is complicated about testing that a function is called when a button is clicked. Are your sagas not tested on their own? Commented Apr 7 at 6:07
  • Yes, in the following lessons we were going through how to test sagas. Would it be a good solution to spy on the userAction instead? const spy = vi.spyOn(userActions, 'signOutStart'); + expect(spy).toHaveBeenCalled(); Commented Apr 7 at 17:50
  • That is likely how I'd test, spy on the action and assert it was called, possibly with a specific argument (e.g. payload). If the action updates state and triggers a component rerender, then it's better to test/assert what happens in the UI when the action updates state. If you are just starting out then I recommend you familiarize yourself with current testing paradigms. See React-Testing-Library for details. Commented Apr 7 at 17:53

1 Answer 1

0

I solved my issue with spying on the user action instead of useDispatch.

test('it should dispatch signOutStart action when clicking on Sign Out link', () => {
  const spy = vi.spyOn(userActions, 'signOutStart');

  renderWithProviders(<Navigation />, {
    preloadedState: {
      user: {
        currentUser: {} 
      }
    }
  });

  const signOutLinkElement = screen.getByText(/sign out/i);
  expect(signOutLinkElement).toBeInTheDocument();
  fireEvent.click(signOutLinkElement);
  expect(spy).toHaveBeenCalled(); 
  spy.mockRestore();
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.