<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Claes</title>
    <description>The latest articles on Forem by Alex Claes (@alexclaes).</description>
    <link>https://forem.com/alexclaes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1089676%2F3aae79c0-dd97-4000-b1b4-27aecdd036a4.jpg</url>
      <title>Forem: Alex Claes</title>
      <link>https://forem.com/alexclaes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alexclaes"/>
    <language>en</language>
    <item>
      <title>Test a hook throwing errors in React 18 with renderHook from Testing Library 🚨🦑</title>
      <dc:creator>Alex Claes</dc:creator>
      <pubDate>Thu, 25 May 2023 20:09:12 +0000</pubDate>
      <link>https://forem.com/alexclaes/test-a-hook-throwing-errors-in-react-18-with-renderhook-from-testing-library-20g8</link>
      <guid>https://forem.com/alexclaes/test-a-hook-throwing-errors-in-react-18-with-renderhook-from-testing-library-20g8</guid>
      <description>&lt;p&gt;When writing React applications, you likely want to use &lt;a href="https://testing-library.com"&gt;Testing Library&lt;/a&gt;. It's a tool specifically designed to test UI components from a user's perspective, encouraging developers to write tests that simulate real user interactions. It comes with a great &lt;a href="https://testing-library.com/docs/react-testing-library/intro"&gt;React integration&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;renderHook&lt;/code&gt; function is a utility that allows you to test custom hooks. It provides a way to render a custom hook in a testing environment and access the values it returns. &lt;code&gt;renderHook&lt;/code&gt; sets up the necessary infrastructure to execute the hook and provides an API to interact with its state and effects, enabling comprehensive testing of the hook's behavior and functionality. It ensures that hooks are tested in isolation, making it easier to write effective unit tests for hooks without the need for rendering a full React component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a hook might throw an error
&lt;/h2&gt;

&lt;p&gt;Oftentimes, you want your custom hook to explicitly throw an error if something is wrong. Possible scenarios could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A hook that relies on certain function arguments and throws if they are not provided correctly.&lt;/li&gt;
&lt;li&gt;A hook that reads the value from a React context and throws if the context provider is not present. &lt;/li&gt;
&lt;li&gt;A hook that depends on an external API and throws if it receives a negative response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In such scenarios, you want to make sure the behavior works as intended, and you can use &lt;code&gt;renderHook&lt;/code&gt; for this purpose.&lt;/p&gt;

&lt;p&gt;First, let's take a look at a custom hook that throws an error. It's an easy one, because it always throws.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;something failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following examples in this article are written for &lt;a href="https://jestjs.io"&gt;Jest&lt;/a&gt;, but the same concept applies to other testing frameworks like &lt;a href="https://mochajs.org"&gt;Mocha&lt;/a&gt; or &lt;a href="https://cypress.io/"&gt;Cypress&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old way before React 18 ❌
&lt;/h2&gt;

&lt;p&gt;Before the release of React 18 &lt;code&gt;renderHook&lt;/code&gt; was provided in a separated package called &lt;a href="https://github.com/testing-library/react-hooks-testing-library"&gt;@testing-library/react-hooks&lt;/a&gt;. To ensure a hook throws an error, they integrated a wrapper that catches occurring errors and provides them under &lt;code&gt;result.error&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This is how you would have tested if a hook throws an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should throw an error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You call the &lt;code&gt;renderHook&lt;/code&gt; function and pass a callback function that calls the hook function. &lt;code&gt;renderHook&lt;/code&gt; returns an object included the &lt;code&gt;result&lt;/code&gt; of the call. In case an error was thrown, you can read &lt;code&gt;result.error&lt;/code&gt;. You can make an assertion in your unit test and compare it to an expected error message.&lt;/p&gt;

&lt;h2&gt;
  
  
  The new way with React 18 ✅
&lt;/h2&gt;

&lt;p&gt;After the release of React 18 the &lt;a href="https://github.com/testing-library/react-hooks-testing-library#details"&gt;authors of Testing Library decided&lt;/a&gt; to integrate the &lt;code&gt;renderHook&lt;/code&gt; utility directly into &lt;code&gt;@testing-library/react&lt;/code&gt; instead of maintaining a separated package for this API.&lt;/p&gt;

&lt;p&gt;As you can read in the &lt;a href="https://github.com/testing-library/react-testing-library/pull/991"&gt;pull request for this change&lt;/a&gt;, testing errors will no longer be solved. This means you need a different approach to ensure a custom hook throws an error.&lt;/p&gt;

&lt;p&gt;This is how you can test for thrown errors now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should throw an error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;  
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty straightforward. It doesn't rely on any additional implementation provided by Testing Library to catch the thrown error and deal with it. Instead, the error simply escalates, and you can handle it yourself, like here with the &lt;a href="https://jestjs.io/docs/expect#tothrowerror"&gt;&lt;code&gt;.toThrow()&lt;/code&gt; matcher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you feel like passing an arrow function to &lt;code&gt;expect&lt;/code&gt; looks a bit funny, this slightly more verbose approach also works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should throw an error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;renderHook&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;useSomething&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;catche&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;something failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are quite a few other things that changed for Testing Library with the release of React 18. You can check out the &lt;a href="https://github.com/testing-library/react-hooks-testing-library/blob/chore/migration-guide/MIGRATION_GUIDE.md"&gt;migration guide&lt;/a&gt; for further information.&lt;/p&gt;

</description>
      <category>react</category>
      <category>testing</category>
      <category>javascript</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
