1

I am trying to test error states of the following MSW rest endpoint:

import { rest } from 'msw'

export const exceptionHandlers = [
  rest.post(config.accountApiUrl + '/login', (req, res, ctx) => {
    return res(
      ctx.status(500),
      ctx.json({ data: { message: 'Mock Error Message' } })
    )
  })
]

This endpoint is called in a custom hook return function thats using React Query's mutateAsync:

  const { mutateAsync } = useMutation(AuthApi.login)

  const handleLogin = async (props): Promise<void> => {
    await mutateAsync(props, {
      onSuccess: async () => {
        // this block tests fine
      }
      onError: async () => {
        console.log('!!!')
        // it reaches this block, '!!!' is logged to the console,
        // but the test still fails with `Request failed with status code 500`
      }
    })
  }

   return handleLogin

In a test file:

  it('handles network errors', async () => {
    mswServer.use(...exceptionHandlers)
    const user = userEvent.setup()
    const screen = render(<LoginForm />)
    const submitButton = screen.getByTestId('Login.Submit')
    // Complete form
    await user.click(submitButton)
  })

It doesnt matter what comes after that, the test always fails with

Request failed with status code 500

      at createError (node_modules/axios/lib/core/createError.js:16:15)
      at settle (node_modules/axios/lib/core/settle.js:17:12)
      at XMLHttpRequestOverride.onloadend (node_modules/axios/lib/adapters/xhr.js:54:7)
      at XMLHttpRequestOverride.trigger (node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts:176:17)
      at node_modules/@mswjs/interceptors/src/interceptors/XMLHttpRequest/XMLHttpRequestOverride.ts:354:16

But its supposed to fail with status 500. That's the whole point. If I change the handler to return another error, ie ctx.status(404), then the test just fails with that error code.

I've tried wrapping the assertion in a try/catch block but the same thing results. I see examples online of people doing (apparently) exactly this and it works fine, so I'm quite confused what's causing this. All other tests that check success states work as expected.

benmneb
  • 1,773
  • 1
  • 15
  • 26
  • Test fails with 500 as you expected. And it does with 404 if you setup so. Whats the problem here again? – JunKim Jun 28 '22 at 16:23
  • 1
    The problem is that it fails the test – benmneb Jun 29 '22 at 02:54
  • are you sure that the test is failing? If so, which error is the test failing with? All I see is that the request error gets logged, which doesn't automatically imply that the test failed. Also, I don't see your test asserting anything? You're getting the login button and then you click it. So what exactly is failing? – TkDodo Jul 01 '22 at 07:36
  • @TkDodo the test is definitely failing, and the only message is `Request failed with status code 500` or whatever code it's supposed to return from MSW. That's all the info I got. Whatever comes after the action that causes the mutation to run in the test is irrelevant, the test always fails before it gets to it. I tried to set up a sandbox/blitz to share but was too complicated – benmneb Jul 11 '22 at 03:17
  • 1
    @TkDodo I've since noticed that this only happens with `mutateAsync` where the `onSuccess` and `onError` blocks are used like in the code in my question, if the hook is refactored to use `try/catch` like you show [in the docs](https://react-query-v3.tanstack.com/guides/mutations#promises), the test passes. So maybe you can help settle a discussion between me and a coworker... if everything else stays the same, is there any benefit/hinderance/difference at all to refactoring all our mutations to use try/catch instead of the onError/onSuccess blocks? Thanks – benmneb Jul 11 '22 at 03:17
  • I would use `mutate` with callbacks because it catches errors internally. With mutateAsync, you have to catch them for yourself. – TkDodo Jul 15 '22 at 07:59

1 Answers1

0

i've had the same problem.

As far as i could understand, the problem is that in test environment there is no handler for the rejected promise.

https://github.com/TanStack/query/issues/4109