Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test components with react hooks?

Currently trying to unit test components with hooks (useState and useEffects). As I have read, lifecycles can only be tested with a mount and not a shallow render.

Implementation code:

export function MainPageRouter({issuerDeals, match, dbLoadIssuerDeals}) {
console.log("MainPageRouter")
const [isLoading, setIsLoading] = useState(true);


const selectedIssuerId = match.params.id;
const issuerDeal = filterIssuerDealByIssuerId(issuerDeals, 
selectedIssuerId);

useEffect(() => {
   dbLoadIssuerDeals(selectedIssuerId)
     .then(() => {
        setIsLoading(false);
      })
     .catch(function (error) {
        setIsLoading(false);
        });
  }, [selectedIssuerId]);

  if (isLoading) {
    return <MainPageLoading />
  } else if(issuerDeal.length > 0) {
    return <MappedDeal match={match}/>
  } else {
    return <MapDeal match={match}/>
  }

}

const mapStateToProps = state => {
  return {
    deals: state.deals,
    issuerDeals: state.issuerDeals
  }
};

const mapDispatchToProps = {
  dbLoadIssuerDeals
}

export default connect(mapStateToProps, mapDispatchToProps)(MainPageRouter);

However doing so results in this error:

Warning: An update to MainPageRouter inside a test was not wrapped in 
act(...).

When testing, code that causes React state updates should be wrapped into 
act(...):

act(() => {
  /* fire events that update state */
});

Test:

it('Should render Mapped Deal', () => {
    const dbLoadIssuerDeals = jest.fn(() => Promise.resolve({
        payload:{ deals: { dealid: "1", sourceCode: "TEST" }, issuerId: "1" } }))
    const props = createProps(issuerDeals, dbLoadIssuerDeals);
    const mainPageRouter = mount(<MemoryRouter><MainPageRouter{...props} /></MemoryRouter>);
});

Is there a clean way to test that mainPageRouter would return back MappedDeal or MapDeal? I also understand that using mount is more towards integration tests.

like image 654
kevin man Avatar asked May 13 '19 15:05

kevin man


People also ask

How do you test a component using a hook?

If you need to test a custom Hook, you can do so by creating a component in your test, and using your Hook from it. Then you can test the component you wrote. To reduce the boilerplate, we recommend using React Testing Library which is designed to encourage writing tests that use your components as the end users do.

How do you unit test a hook React?

There are two methods we need to know in react-hooks-testing-library. The first is renderHook , the second is act : renderHook : The renderHook can render custom hook, you can operations the custom hook like in the component. act : The act can execute the methods return from custom hook.

Should I unit test React components?

Unit Testing is important for React Apps, as it helps in testing the individual functionality of React components.

Can you test React hooks with Jest?

Testing React Hooks with Jest and Enzyme. Jest and Enzyme are tools used for testing React apps. Jest is a JavaScript testing framework used to test JavaScript apps, and Enzyme is a JavaScript testing utility for React that makes it easier to assert, manipulate, and traverse your React components' output.


1 Answers

The warning you're getting isn't caused by using hooks per see but because you have a side-effect that causes a state update.

Something is happening after your component's initial render: you're fetching data from your dbLoadIssuerDeals service and updating the local state, resulting in a re-render. However, your test runs right after the first render, meaning it couldn't properly assert anything happening after the effect. You could basically only test that MainPageLoading is displayed, but none of the other branching statements. React's act testing API is warning you about that.

Running your code in act guarantees the execution of state updates and enqueued side-effects. In other words, it lets you "wait" for changes resulting from state updates. You can read more about act in React's official docs.

I recommend using React Testing Library instead of Enzyme or the test utilities of React DOM directly. It wraps updates and events in act for you, allowing you to write more expressive tests without the boilerplate.

like image 50
Sarah Dayan Avatar answered Oct 08 '22 19:10

Sarah Dayan