JEST test for my component to throw an exception inside useEffect

Viewed 2752

The following component works. However I'm wondering how I can use assertions to test for it to throw an error.

No it's using context to provide values to my project. But I'm not sure if that's relevant for this question, but I wanted to add it anyway. I hope it should be possible to just assert on the error to be thrown regardless of the fact that the component is in context.

./MyContext.jsx

// ... generic imports left out for brevity
import request from './request';

const MyContext = createContext([{}, () => {}]);

const fetchList = async (url) => request(url);

const MyContextProvider = ({ children }) => {
  const [list, setList] = useState({
    fetchStatus: undefined,
    data: [],
  });

  const apiUrl = 'https://www.example.com/my-api/';

  useEffect(() => {
    setList({ fetchStatus: 'pending' });
    
    fetchList(apiUrl)
      .then((response) => {
        if (!response.success) {
          // 
          // this is what I want to test
          // 
          throw new Error(`The list fetch on ${apiUrl} was not successful.`);
        }
        setList({ data: response, fetchStatus: 'success' });
      })
      .catch(() => {
        setList({ fetchStatus: 'error' });
      });
  }, [apiUrl, setList]);

  return (
    <MyContext.Provider value={{ list }}>
      {children}
    </MyContext.Provider>
  );
};

export { MyContext, MyContextProvider };

Then in the test:

./SomeComponent.spec.js

// ... generic imports left out for brevity
import { MyContext, MyContextProvider } from './MyContext';
import request from './request';

jest.mock('../../../shared/request');

function Wrapper ({children}) {
  return (
    <MyContextProvider>{children}</MyContextProvider>
  )
}

async function setup() {
  let context;
  const TestComponent = () => {
    context = React.useContext(MyContext);
    return '<></>';
  }
  
  await act(async () => {
    render(<TestComponent />, { wrapper: Wrapper });
  });

  return context;
}

// PASS!
it('when request fetch fails it returns with fetchStatus error', async () => {
  const data = { success: false };
  request.mockResolvedValue(data);
  const { readSchedules } = await setup();
  expect(readSchedules).toEqual({ fetchStatus: 'error' });
});

// UNSURE HOW TO TEST FOR THE EXCEPTION TO THROW
it('throws an exception if the request response is invalid', async () => {
  const data = { success: false };
  request.mockResolvedValue(data);
  await setup();

  const error = 'The list fetch on https://www.example.com/my-api/ was not successful.';

  // How should I get this one?
  expect(??).to.throw(Error(error));
});

I hope this explains the issue I'm facing.

1 Answers

The effect doesn't throw an error but handles it. Since catch doesn't use caught error, it doesn't affect the result.

It should be the same as for unsuccessful response:

request.mockRejectedValue(new Error('whatever'));
await setup();
const { readSchedules } = await setup();
expect(readSchedules).toEqual({ fetchStatus: 'error' });
Related