<?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>DEV Community: Daria Caraway</title>
    <description>The latest articles on DEV Community by Daria Caraway (@dariacaraway).</description>
    <link>https://dev.to/dariacaraway</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%2F193423%2F26ff68ef-1fb3-43bb-a4f6-4b55b99ff9de.jpeg</url>
      <title>DEV Community: Daria Caraway</title>
      <link>https://dev.to/dariacaraway</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dariacaraway"/>
    <language>en</language>
    <item>
      <title>Unhandled Async Calls Cause Flaky Jest Tests</title>
      <dc:creator>Daria Caraway</dc:creator>
      <pubDate>Mon, 12 Apr 2021 23:40:40 +0000</pubDate>
      <link>https://dev.to/dariacaraway/unhandled-async-calls-cause-flaky-jest-tests-189a</link>
      <guid>https://dev.to/dariacaraway/unhandled-async-calls-cause-flaky-jest-tests-189a</guid>
      <description>&lt;p&gt;Have you ever come across a Jest test failure that seemed completely random and was incredibly frustrating? Most of the time when this happens to me, it's because I have an unhandled asynchronous error wreaking havoc on my testing suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Symptoms
&lt;/h2&gt;

&lt;p&gt;These are some symptoms that you might have a flakey failure due to mishandling an async call.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different tests are "randomly" failing in the same file on different test runs.&lt;/li&gt;
&lt;li&gt;When you run the tests individually, they all pass.&lt;/li&gt;
&lt;li&gt;When you run a subset of the tests, they all pass.&lt;/li&gt;
&lt;li&gt;When you give the tests more resources to run faster, they all pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Cause
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Say you have an asynchronous test:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&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 add 1 + 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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;asyncFunctionFails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// kicks off on async call that will eventually throw&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;asyncFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// kicks off a successful async call that is awaited&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;synchronousAddOneFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;testValue&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;// test ends&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;asyncFunctionFails&lt;/code&gt; is an asynchronous function that does some work and eventually throws an exception in the testing environment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;asyncFunction&lt;/code&gt; is an asynchronous function that is correctly &lt;code&gt;awaited&lt;/code&gt; before the test continues. When this function is called with &lt;code&gt;await&lt;/code&gt;, the test yields the thread back to process &lt;code&gt;asyncFunctionFails&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When run on its own, this test passes even though &lt;code&gt;asyncFunctionFails&lt;/code&gt; will throw an exception. Why? The test process finishes before &lt;code&gt;asyncFunctionFails&lt;/code&gt; has the chance to throw the error because nothing is telling the thread to wait for it, so Jest reports a success. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl1s2xaiu8wgw4bvn9s5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnl1s2xaiu8wgw4bvn9s5.png" alt="Jest test output of a single test that is passing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  But what if you have other tests in the same file?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&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 add 1 + 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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;asyncFunctionFails&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// eventually throws&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;asyncFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;synchronousAddOneFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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;testValue&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;it&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 add 2 + 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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;await&lt;/span&gt; &lt;span class="nf"&gt;asyncFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;synchronousAddOneFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;testValue&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;it&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 add 3 + 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &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;await&lt;/span&gt; &lt;span class="nf"&gt;asyncFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;synchronousAddOneFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&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;testValue&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="mi"&gt;4&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;When you run this whole test file, one of them fails:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcugvp1zsaajl4mylo0m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcugvp1zsaajl4mylo0m.png" alt="Jest test output of three tests. The first and third are passing, the second is failing."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why does the second test fail when the first test is the one that calls the problematic function?&lt;/p&gt;

&lt;p&gt;Now that there are more tests, the Jest process has more time to run than when there was only one test, meaning &lt;code&gt;asyncFunctionFails&lt;/code&gt; has a chance to process and throw an exception. So, when the exception is thrown, the Jest process has already moved past the first test and will attribute failure to whichever test happens to be running.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sweet Race Condition!
&lt;/h3&gt;

&lt;p&gt;This bug is one of the hardest to track down because depending on how many tests you have in the file or how fast the tests take to run, the failures might seem to pop up randomly. &lt;/p&gt;

&lt;p&gt;Most of the time, too, the async calls are not as straightforward as this example. Maybe you are mounting a React component that kicks off 5 different hooks to fetch data before rendering in the dom. Or perhaps you are calling a function that fires events to 5 different listeners that each executes code. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;Make sure to await for the expected outcome or mock out any timers, so all of the code has a chance to run. The exception may still be thrown, but Jest will attribute the error to the correct test. Doing this will make everything much more straightforward to debug. &lt;/p&gt;

&lt;p&gt;To address the exception, you may be able to mock out the asynchronous behavior. For example, if the call fails trying to get data from a server, mock the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Yay!
&lt;/h2&gt;

&lt;p&gt;I hope this post helps save you some time debugging a seemingly random test failure. Double-checking your async calls might be the key to stable passing tests :).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkdaaaqaoboba487xr6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkdaaaqaoboba487xr6b.png" alt="Jest test output of three tests passing."&gt;&lt;/a&gt;&lt;/p&gt;

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