title: How to test for Failure Action in Jest using runSaga
body: <p>I've tested a successful response, but I'm having trouble with a failing response. </p>
  
  <p>Here's the action:</p>
  
  <pre class="lang-js prettyprint-override"><code>export function* searchSaga({ searchParams }) {
    try {
      const { text, customers, searchField } = searchParams;
      const results = customers.filter(c =&gt; c[searchField] === text);
      yield put({
        type: "CUSTOMER_SEARCH_SUCCESS",
        results
      });
    } catch (error) {
      yield put({
        type: "CUSTOMER_SEARCH_FAILURE",
        error
      });
    }
  }
  </code></pre>
  
  <p>The test for success passes:</p>
  
  <pre class="lang-js prettyprint-override"><code>  const initialAction = { type: "SEARCH_CUSTOMERS_START", searchParams };
    it("searches customers with a saga", async () =&gt; {
      const dispatched = await recordSaga(searchSaga, initialAction);
      const expectedAction = {
        type: "CUSTOMER_SEARCH_SUCCESS",
        results: [customers[0]]
      };
      expect(dispatched).toContainEqual(expectedAction);
    });
  </code></pre>
  
  <p>When I try to test the failure, however, the error I'm throwing in my mock gets in the way:</p>
  
  <pre class="lang-js prettyprint-override"><code>it("returns an error on a failure", async () =&gt; {
      const error = new Error("uh oh!");
      Array.prototype.filter = jest.fn();
      Array.prototype.filter.mockImplementation(() =&gt; throw error);
      const dispatched = await recordSaga(searchSaga, initialAction);
      const expectedAction = { type: "CUSTOMER_SEARCH_FAILURE", error };
      console.log(dispatched);
      expect(dispatched).toContainEqual(expectedAction);
    });
  </code></pre>
  
  <p>The output from this test includes the thrown error, however the console shows that the correct failure action was also dispatched!</p>
  
  <pre class="lang-js prettyprint-override"><code> ● Console
  
      console.log __tests__/CustomerSearch.test.js:48
        [ { type: 'CUSTOMER_SEARCH_FAILURE',
            error:
             Error: uh oh!
                 at _callee2$ (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/__tests__/CustomerSearch.test.js:43:19)
                 at tryCatch (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:45:40)
                 at Generator.invoke [as _invoke] (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:271:22)
                 at Generator.prototype.(anonymous function) [as next] (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:97:21)
                 at tryCatch (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:45:40)
                 at invoke (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:135:20)
                 at /Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js:170:11
                 at tryCallTwo (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/promise/lib/core.js:45:5)
                 at doResolve (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/promise/lib/core.js:200:13)
                 at new Promise (/Users/TuzMacbookPro2017/Development/QMG-local/APPS/QMGProzReviews/node_modules/promise/lib/core.js:66:3) } ]
  
    ● searchCustomers › returns an error on a failure
  
      uh oh!
  
        41 | 
        42 |   it("returns an error on a failure", async () =&gt; {
      &gt; 43 |     const error = new Error("uh oh!");
           |                   ^
        44 |     Array.prototype.filter = jest.fn();
        45 |     Array.prototype.filter.mockImplementation(() =&gt; throw error);
        46 |     const dispatched = await recordSaga(searchSaga, initialAction);
  
  </code></pre>
  
  <p>Now, I've tried wrapping this in a try/catch block:</p>
  
  <pre class="lang-js prettyprint-override"><code>it("returns an error on a failure", async () =&gt; {
      const error = new Error("uh oh!");
      Array.prototype.filter = jest.fn();
      Array.prototype.filter.mockImplementation(() =&gt; throw error);
      try {
        const dispatched = await recordSaga(searchSaga, initialAction);
      } catch (e) {
        console.log(dispatched);
        const expectedAction = { type: "CUSTOMER_SEARCH_FAILURE", error };
        expect(dispatched).toContainEqual(expectedAction);
      }
    });
  </code></pre>
  
  <p>And this does pass, however, it's a false positive. If I change, for instance, the type of the expected action to any nonsense, the test still passes.</p>
  
  <p>How do I make this work?</p>
  
  <p>Edit:
  I noticed that the <code>console.log(dispatched)</code> was never getting activated in that last passing example. I added a copy of that log statement in the <code>try</code> block, and I see that I <em>am</em> getting the correct failure action returned. </p>
  
  <p>Playing around with logging, it seems like the error is being thrown and caught in some strange places. </p>
  
  <pre class="lang-js prettyprint-override"><code> it("returns an error on a failure", async () =&gt; {
      const error = new Error("uh oh!");
      Array.prototype.filter = jest.fn();
      Array.prototype.filter.mockImplementation(() =&gt; throw error);
      const expectedAction = { type: "CUSTOMER_SEARCH_FAILURE", error };
      try {
        const dispatched = await recordSaga(searchSaga, initialAction);
        console.log("***DISPATCHED FROM TRY IN TEST***", dispatched);
        expect(dispatched).toContainEqual(expectedAction);
      } catch (e) {
        console.log("***ERROR FROM CATCH IN TEST***", e);
      }
    });
  </code></pre>
  
  <p>The above logs the correct dispatched actions from the try block, and then logs the "uh oh" error from the catch block. Removing the last line of the <code>try</code> block logs the correct actions from the try block, and that's it, it passes. It passes, of course, because there are no assertions to fail. </p>
  
  <p>So it appears to be the actual assertion that's throwing the error. I can't figure out when the error being thrown and how to avoid it.</p>