testing-library / react-hooks-testing-library

🐏 Simple and complete React hooks testing utilities that encourage good testing practices.
https://react-hooks-testing-library.com
MIT License
5.25k stars 230 forks source link

Cannot test async useCallback in custom hook #951

Closed mljlynch closed 1 year ago

mljlynch commented 1 year ago

What is your question:

Consider I have a custom hook that contains a few callbacks

const useDummyHook= ()=>{
  const useAysncCallback = useCallback(async(foo:string) =>{
    if(foo !== "bar){
      throw new Error("foo did not equal bar);
    }
  })
}

I want to test this error throws using renderHook. I cannot get the following to pass:

it('should throw an error if foo does not equal bar', async ()=>{
   const { result } = renderHook(()=>useDummyHook())
   await expect(async() =>{
     result.current.useAysncCallback("notBar")
  }).toThrow()
})

When I run the test, the test says the given function has not thrown an error, but If i do not assert that an error is thrown the test throws an error.

Am I using the custom hooks wrong? Am I missing something in renderHook?

mpeyper commented 1 year ago

Try adding an await inside the expect callback:

it('should throw an error if foo does not equal bar', async ()=>{
   const { result } = renderHook(()=>useDummyHook())
   await expect(async() =>{
     await result.current.useAysncCallback("notBar")
  }).toThrow()
})
mljlynch commented 1 year ago

Running:

it('should throw an error if foo does not equal bar', async ()=>{
   const { result } = renderHook(()=>useDummyHook())
   await expect(async() =>{
     await result.current.useAysncCallback("notBar")
  }).toThrow()
})

Jest fails since it did not throw

if I run the following:

it('should throw an error if foo does not equal bar', async ()=>{
   const { result } = renderHook(()=>useDummyHook())
   await result.current.useAysncCallback("notBar")
})

jest fails, but does not say an error was thrown:

    foo did not equal bar

      }
       if (foo !== "bar") {
      throw new Error("foo did not equal bar"); 
               ^
       }

      at call 
      at tryCatch (node_modules/regenerator-runtime/runtime.js:63:40)
mljlynch commented 1 year ago

This also doesn't work


 await expect(async () => {
      const asyncFunc = async () => Promise.reject(new Error('Foo'));
      await asyncFunc();
    }).toThrow();
mljlynch commented 1 year ago

The resolution to this was covered here: https://stackoverflow.com/questions/75377144/expect-an-async-function-to-throw-an-error-in-jest