1

Is there a way to test functional components built using React hooks by shallow mounting the component. I came across Enzyme not supporting useEffect (https://airbnb.io/enzyme/#react-hooks-support) and other hooks with shallow rendering a component and I don’t want to get into mount.

Also came across react-testing-library being a new and popular alternative. Is it better option compared to Enzyme? I already have Enzyme used for testing class based components. So, there is a pain involved in rewriting those.

3
  • Any reason why you do not want to fully render it? Even though it is troublesome to use mount (especially if you are rendering a connected component), I still think it is the most straight forward way to test its behaviour Commented Jan 30, 2020 at 7:57
  • @wentjun I would like to separately test each component as a unit hence shallow is what I prefer. Commented Jan 30, 2020 at 8:02
  • Ahh I see.. Makes sense. I would have preferred shallow rendering in that scenario as well. Commented Jan 30, 2020 at 8:11

1 Answer 1

3

Yes you can but will need to use spies. For example if you are using jest you can you use jest.spyOn with mockImplementationOnce(), It should also work with other spying libraries.

Using Example:

describe("React useEffect", () => {
  let useEffect, wrapper

  let mockUseEffect = () => {
    useEffect.mockImplementationOnce(f => f())
  }

  beforeEach(() => {
    useEffect = jest.spyOn(React, "useEffect")

    mockUseEffect()
    wrapper = shallow(<SomeComponent />)
  })

  it("your test", () => {
     // using wrapper
  })
}

Here is a nice detailed article by "Will Ockelmann-Wagner" and I added a codeSandbox working example.


Although it works, I'd encourage you to not use shallow rendering and start using react-testing-library (called @testing-library/react nowadays), Its well-documented, lightweight Testing solution, and I'd say its the the "closest" test you can get to real world scenarios. It comes already with CRA by default.

Here a basic codeSandbox example and Here is more examples from React Docs.

Also, here is a great Video by Kent C. Dodds that addressing the differences between shallow rendering and the render approach from react testing library.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks for nicely explained answer! Read about react-testing-library recently. Found that it uses full mount and doesn't support shallow. If thats the case even enzyme is good to test hooks in functional components using mount. Why react-testing-library then?
I wasn't actually talking about hooks only but generally speaking why should you consider using RTL for your tests. RTL is like forcing you to write better testing logic and not to do "shallow" tests that might focus on implementation rather than the functionality of your components. Its about the perspective actually not the way.
For instance, when rendering a component using Enzyme, it allows you to access the full component’s data (props, state, children, …) which mostly leads you to test its implementation, RTL has a different approach, you only have access to the elements that are in the DOM, no internal state, no methods, just what the user can interact with. Thus, that would leads you to rethink of how and what to test. RTL tests are more focused on the end user behavior.
"We recommend using React Testing Library which is designed to enable and encourage writing tests that use your components as the end users do. Alternatively, Airbnb has released a testing utility called Enzyme, which makes it easy to assert, manipulate, and traverse your React Components’ output." Docs
I'm really glad that I could help. Btw, Kent C. Dodds (the RTL author) has a great YouTube channel with tons of professional and very useful content.
|

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.