Unit testing render prop component in React
Tags: react, javascript, testing, jest
Published: 2019-06-07 19:04:08

---
title: Unit testing render prop component in React
published: true
description: How to unit test component that is using render prop
tags: react, javascript, testing, jest
---

## What is a render prop?

Render prop is a pattern that is widely used in React ecosystem. In a nutshell, render prop is a pattern in which you are passing a function as a prop, usually called `render` or more commonly as a `children` prop. For example:

```javascript
import React from 'react';

const RenderPropComponent = ({children}) => {
  const [counter, setCounter] = React.useState(0)  

  return children({counter, setCounter});
};

// usage
const Usage = () => {
  return (
    <RenderPropComponent>
      {({counter}) => <p>Counter: {counter}</p>}
    </RenderPropComponent>
  );
};
```
If you want to read more extensively about render props pattern in React and their usage in React ecosystem check [this](https://dev.to/maksimovicdanijel/render-props-pattern-in-react-3f8) post.

## Test preparation

In order to test render prop component, we should first write one! Our component will fetch posts from an API and expose loading state and posts to a consumer component.

```javascript
import React from 'react';
import PropTypes from 'prop-types';

import { fetchPosts } from './api';

export default class FetchPosts extends React.Component {
  static propTypes = {
    children: PropTypes.func.isRequired
  };

  state = { posts: [], loading: false };

  async componentDidMount() {
    this.setState({ loading: true });

    const posts = await fetchPosts();

    this.setState({ posts, loading: false });  
  }

  render() {
    return this.props.children({posts: this.state.posts, loading});
  }
}
```

## Writing the test

We are going to write our test using `jest` and `react-testing-library` but the same principles apply if you use something else to write your tests.

```javascript
import React from 'react';
import { render } from 'react-testing-library';

import FetchPosts from './FetchPosts';

const mockPosts = [{ id: 1, title: 'Title' }];

jest.mock('./fetchPosts', () => Promise.resolve(mockPosts));

describe('FetchPosts component test', () => {
  it('should expose loading and posts prop', () => {
    const postsCallbackMock = jest.fn();

    const { getByTestId } = render(
      <FetchPosts>{postsCallbackMock}</FetchPosts>
    );

    expect(postsCallbackMock).toHaveBeenCalledWith({
      loading: false,
      posts: mockPosts
    })
  });
});

```

This is one a bit simpler way to test render prop component. Another way is to write a consumer component which renders something on the page and then expect it matches with the data that you received. For example:

```javascript
import React from 'react';
import { render } from 'react-testing-library';

import FetchPosts from './FetchPosts';

const mockPosts = [{ id: 1, title: 'Title' }];

jest.mock('./fetchPosts', () => {
  return new Promise(resolve => {
    setTimeout(() => resolve(mockPosts), 100);
  });
});

const FetchPostsConsumer = () => (
  <FetchPosts>
    {({loading, posts}) => {
      if(loading) return <span data-testid="loading"></span>;

      return posts.map(post => <p data-testid="post-title">{post.title}</p>)
    }}
  </FetchPosts>
);

describe('FetchPosts component test', done => {
  it('should return correct loading and posts props', () => {
    const postsCallbackMock = jest.fn();

    const { getByTestId } = render(
      <FetchPostsConsumer />
    );

    expect(getByTestId('loading').textContent).toBe('Loading');

    setTimeout(() => {
      expect(getByTestId('post-title').textContent).toBe('Title');
      done()
    })
  });
});

``` 

At the beginning of this test, we are declaring what our `fetchPosts` module is returning so we can have the same results on each test run (these tests are called deterministic). This mocked version of a function is resolving a promise but after some timeout, which gives us enough time to inspect the loading state later in our test.

Next, we are declaring a component that is using render prop component that we really want to test. After the component is rendered we are checking if loading text is present. After some time, we are checking if the correct post is being rendered as a result of render prop callback. This approach is a bit longer but in my opinion, it gives us a bit more user-oriented test which in the end is how users are going to use our component.

## Conclusion

As you can see testing render prop component is not that difficult in the end. Since that kind of a component doesn't generate an output by itself we have to provide that missing part in our test and then do the assertions. A simpler way is to just provide a mock function and expect that it's called with correct parameters. Which approach do you like more? Share it in the comments below 👇