React-hooks-testing-library: How to test useReducer dispatch that errors?

Created on 17 Apr 2019  路  4Comments  路  Source: testing-library/react-hooks-testing-library

What is your question:

How can I test that a reducer dispatch results in an error?

The renderHook api returns a result object with an error key. The docs state that this is an error that is thrown if the callback function threw an error during rendering. I'm trying to test for an error from a subsequent dispatch, not from the initial renderHook call.

Dan Abrmaov suggests that with useReducer, the default switch case should throw an error: https://twitter.com/dan_abramov/status/1093969005675773954?lang=en

import { useReducer } from 'react';
import { act, renderHook } from 'react-hooks-testing-library';

const initialState = {};

function reducer(state, action) {
  switch (action.type) {
    default: 
      throw new Error('Unknown action type');
  }
}

test('throws an error when dispatched with an unknown action type', () => {
  expect.assertions(1);

  const { result } = renderHook(() => useReducer(reducer, initialState));
  const [, dispatch] = result.current;

  try {
    act(() => {
      dispatch({ type: 'whaaat' });
    });
  } catch (e) {
    // asserting here does not appear to be the right approach
  }
});

Would the best approach be to render the test by wrapping it in an ErrorBoundary type component and testing for the resulting render?

As it stands, I get the following reported, just not sure how to catch/handle it in my test.

Screen Shot 2019-04-17 at 9 37 10 AM
Screen Shot 2019-04-17 at 9 37 06 AM

question

All 4 comments

If it's catching in the ErrorBoundary, then try checking the result.error property.

test("throws an error when dispatched with an unknown action type", () => {
  expect.assertions(1);

  const { result } = renderHook(() => useReducer(reducer, initialState));
  const [, dispatch] = result.current;

  act(() => {
    dispatch({ type: "whaaat" });
  });

  expect(result.error).toEqual(Error("Unknown action type"));
});

Here is the test passing in a sandbox

Ah.. that makes sense, thank you for the help!

@mpeyper , is there a way to suppress the console.error message that's coming from ErrorBoundary?

This test is passing:

  it('should throw if the initialVariant does not exist', () => {
    const { result } = renderHook(() =>
      useProductVariant(dummyProduct, { initialVariant: '2' })
    );
    expect(result.error.message).toBe(
      'There is no variant with the id "2" on the product Dummy Product'
    );
  });

But I still see this in the console:

  console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:9215
    The above error occurred in the <TestHook> component:
        in TestHook
        in Suspense
        in ErrorBoundary

    React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary.

I know one option is to create a global console.error - but I'd rather leave it in place for other scenarios when i would like those warnings to show up. Is there some kind of middle ground?

You may want to take a look at #50 as there was a better way but the switch to react-test-renderer broke it. I've raised an issue in the React repo, but it has not had any response yet. I'm getting pretty close to just removing the ErrorBoundary and going back to basic try/catch as the warning is pretty annoying.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FredyC picture FredyC  路  3Comments

mtinner picture mtinner  路  3Comments

davidgtu picture davidgtu  路  6Comments

Kiiiwiii picture Kiiiwiii  路  3Comments

Schwartz10 picture Schwartz10  路  4Comments