JavaScript testing #10. Advanced mocking with Jest and React Testing Library

React Testing

This entry is part 10 of 18 in the JavaScript testing tutorial

In the fourth part of this series, we’ve learned the basics of mocking API calls. However, there are often situations where we would like to test various more demanding cases. So, in this article, we implement more advanced examples on how to mock with Jest.

Creating a simple React component

Let’s start by creating a straightforward React component that renders a list of posts.

Posts.tsx

The logic of storing the data in the state resides in the hook.

usePostsLoading.tsx

The function takes care of fetching the data. It is the one we will mock in this article.

fetchPosts.tsx

Mocking a function

In the fourth part of this series, we’ve defined mocks in the directory. Instead, we can mock a function at the top of our test file.

Mocking a named export

Let’s rewrite our file to use a named export for a moment.

fetchPosts.tsx

With the above approach, it is straightforward to mock a module.

Above, we use function that creates a mock function. For example, we can use it to change the value that a function returns. In our case, we force the function to return a promise that resolves to an empty array.

Mocking a default export

Our original file uses a default export. Therefore, we need to modify our mock a bit.

We can simplify the above mock a little by using the method.

Posts.test.tsx

The returns a promise that resolves to an empty array thanks to the above. Because of that, the Posts component does not make an actual HTTP request.

A crucial thing to notice in our test is that our function is still asynchronous. Since we use , our test waits up to 1000ms for the to appear. If the React Testing Library does not find the element during that time, it throws an error, and our test fails.

Mocking a function differently per test

Above, we create a mocked version of the function that always returns the same value. Instead, we might want to mock a function differently per test. Let’s start by using the function on top of our test.

Thanks to doing the above, our function is now replaced with a mock function. The crucial thing to acknowledge is that when we import  in or , we import an instance of a mock function. So we can use this fact and interact with our mock through the test to change what it returns in .

Posts.test.tsx

Since the function that we import on top of our test now has a value of , we can call and on it. We can achieve a different mocked value per test by manipulating the mock before each test.

Mocking a React component

When writing tests with Enzyme, we can choose to either render a component with all of its children or perform a shallow render. In contrast, we don’t have this option with React Testing Library.

The idea behind React Testing Library is to write tests that resemble the way the users interact with our application. Because of that, mocking React components is discouraged. Even though that’s the case, we sometimes might want to avoid testing some components as a whole. The above might happen when using third-party libraries, for example.

DataViewer.tsx

In our test, let’s find out if the renders the component when provided with a dictionary.

DataViewer.test.tsx

Without mocking the react-json-view library above, we wouldn’t have a straightforward way of checking whether our component rendered it when using React Testing Library.

Mocking a module partially

So far, we’ve constantly mocked a whole module when using . We might not want to do that in every case. Let’s imagine having the following file:

utilities.tsx

If we want to mock only the function, we can pair with . When we call , we can retrieve the original content of a module even if we mocked it.

Summary

In this article, we’ve gone through various use-cases of mocking functions. This included real-life situations such as mocking a function differently per test, mocking a default export, or mocking a React component. We’ve also learned how to mock a module partially. All of the above provides a cheat sheet that might come in handy in various cases.

Series Navigation<< JavaScript testing #9. Replacing Enzyme with React Testing LibraryJavaScript testing #11. Spying on functions. Pitfalls of not resetting Jest mocks >>
Subscribe
Notify of
guest
3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Marek
Marek
2 years ago

I’d recommend using msw for mocking APIs, in your case “fetchPosts”

Yaron
Yaron
1 year ago

How’d you mock a function that declared inside a react component and is used inside it’s own view ?

anon
anon
1 year ago
Reply to  Yaron

not sure if you can, perhaps you could abstract it out to its function from another module or pass it as a React component prop, both of which can be mocked