Plz yurn on JavaScript

Create and Test a Hook in React-Native

October 13, 20192 minutes to read

  • #jest
  • #javascript
  • #testing
  • #react
  • #react-native
  • #react-hook

In React 16.8 Hook was introduced. This was kind of mind-blowing for me. First time I did see those I was like ok this is just some kind of syntax sugar etc. But after playing with Hooks for like months I'm loving this. The first thing they makes is to let sharing code easier. In the past Class component was great, but did you try to share some code with that? It's not easy. For me hook even give me a lot of love back to React.

So why this post? One thing I did find online is how to create Hook. Perfect great, but how can I test them? Also, one thing I find missing in React-Native's tutorial is testing. I have a youtube channel and like others React-Native developer on this platform "even Udemy etc" we don't show testing. It's normal too, cause testing take lot of time. So when doing example like me a big tutorial series of already 40+ videos imagine adding testing.

So here I will try to show you how you can start doing a bit more test in React-Native and also how to do this with Hook.

P.S I'm not saying I'm an expert here, just want to help you to get more into testing.

First thing, a library that will make our lives easier is react-hooks-testing-library. This will help us a lot in this process. One reason is the fact then this will help us testing Hook without mounting components. So the unit testing of the Hook will be painless.

useStatusBar

For the first demo, we will make a simple Hook who will set the statusBar color when the screen is focused. For this we will also use the library react-navigation-hooks

This use typescript but can use plain javascript just remove the types :)

1import { useEffect } from 'react';
2import { StatusBar, StatusBarStyle } from 'react-native';
3import { useFocusState } from 'react-navigation-hooks';
4
5const useStatusBar = (style: StatusBarStyle, animated = true) => {
6 const { isFocused } = useFocusState();
7
8 useEffect(() => {
9 if (isFocused) {
10 StatusBar.setBarStyle(style, animated);
11 }
12 }, [isFocused]);
13};
14
15export default useStatusBar;

Here as you can see it's a pretty simple case. The Hook will run a effect when the isFocused boolean value will change. This will happen when the sceen get focused.

Now how can we test that?

The first thing we will need is to create a file call useStatusBar.test.ts Inside this one we will need to render the hook first

1import { renderHook } from '@testing-library/react-hooks';
2
3import useStatusBar from '../useStatusBar';
4
5describe('useStatusBar', () => {
6 it('should set the status bar style as light-content when screen is focused', () => {
7 renderHook(() => useStatusBar('light-content'))
8 });
9});

The hook first argument is the style we do want. Here, in this case, we want light-content the second argument is a default animated value to true. As you can see render the Hook is simple. Time to add some testing. The first thing we need to do for accomplishing the Unit Test is to mock dependencies. In this one we have 2 deps to mock. The StatusBar native API and the react-navigation hook.

How can we do this? Jest to the rescue!!!

Jest came with Spy + Mock and this is all we need. So first time to spy on the StatusBar API.

1import { StatusBar } from 'react-native';
2import { renderHook } from '@testing-library/react-hooks';
3
4import useStatusBar from '../useStatusBar';
5
6describe('useStatusBar', () => {
7 it('should set the status bar style as light-content when screen is focused', () => {
8 const setBarStyleSpy = jest.spyOn(StatusBar, 'setBarStyle');
9
10 renderHook(() => useStatusBar('light-content'))
11 });
12});

As you can see, we create a variable call setBarStyleSpy who will be a spy on the method from the StatusBar setBarStyle. We will spy on this one so we can make sure we do call this method once with the value we expected.

1import { StatusBar } from 'react-native';
2import { renderHook } from '@testing-library/react-hooks';
3
4import useStatusBar from '../useStatusBar';
5
6describe('useStatusBar', () => {
7 it('should set the status bar style as light-content when screen is focused', () => {
8 const setBarStyleSpy = jest.spyOn(StatusBar, 'setBarStyle');
9
10 renderHook(() => useStatusBar('light-content'))
11
12 expect(setBarStyleSpy).toHaveBeenCalledTimes(1);
13 expect(setBarStyleSpy).toHaveBeenCalledWith('light-content', true);
14 });
15});

Here we do check setBarStyle did get called only once and the value provided was light-content and true who is the default value pass.

In the last step we do need to mock the react-navigation-hooks.

1import { StatusBar } from 'react-native';
2import { renderHook } from '@testing-library/react-hooks';
3
4import useStatusBar from '../useStatusBar';
5
6describe('useStatusBar', () => {
7 it('should set the status bar style as light-content when screen is focused', () => {
8 const setBarStyleSpy = jest.spyOn(StatusBar, 'setBarStyle');
9
10 jest
11 .spyOn(reactNavigationHooks, 'useFocusState')
12 .mockImplementation(() => ({ isFocused: true }));
13
14 renderHook(() => useStatusBar('light-content'))
15
16 expect(setBarStyleSpy).toHaveBeenCalledTimes(1);
17 expect(setBarStyleSpy).toHaveBeenCalledWith('light-content', true);
18 });
19});

Here we mock only once the useFocusState method to return an object who contain isFocused: true this one will trigger the useEffect of our hook who then will cause the StatusBar setBarStyle to get a call.

That's it this is how we can use jest and mock/spy on dependencies of our code so we can Unit Test easily.

Previous

Golang Rest API for NodeJS developer - Intro

Next

Table driven test with jest

Subscribe to the Newsletter

Receive notification when new article get posted

Comments