【问题标题】:How to test for Failure Action in Jest using runSaga如何使用 runSaga 在 Jest 中测试失败操作
【发布时间】:2019-06-12 04:57:48
【问题描述】:

我测试了一个成功的响应,但我遇到了响应失败的问题。

下面是动作:

export function* searchSaga({ searchParams }) {
  try {
    const { text, customers, searchField } = searchParams;
    const results = customers.filter(c => c[searchField] === text);
    yield put({
      type: "CUSTOMER_SEARCH_SUCCESS",
      results
    });
  } catch (error) {
    yield put({
      type: "CUSTOMER_SEARCH_FAILURE",
      error
    });
  }
}

成功测试通过:

  const initialAction = { type: "SEARCH_CUSTOMERS_START", searchParams };
  it("searches customers with a saga", async () => {
    const dispatched = await recordSaga(searchSaga, initialAction);
    const expectedAction = {
      type: "CUSTOMER_SEARCH_SUCCESS",
      results: [customers[0]]
    };
    expect(dispatched).toContainEqual(expectedAction);
  });

但是,当我尝试测试失败时,我在模拟中抛出的错误阻碍了:

it("returns an error on a failure", async () => {
    const error = new Error("uh oh!");
    Array.prototype.filter = jest.fn();
    Array.prototype.filter.mockImplementation(() => throw error);
    const dispatched = await recordSaga(searchSaga, initialAction);
    const expectedAction = { type: "CUSTOMER_SEARCH_FAILURE", error };
    console.log(dispatched);
    expect(dispatched).toContainEqual(expectedAction);
  });

这个测试的输出包括抛出的错误,但是控制台显示正确的失败动作也被调度了!

 ● 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 () => {
    > 43 |     const error = new Error("uh oh!");
         |                   ^
      44 |     Array.prototype.filter = jest.fn();
      45 |     Array.prototype.filter.mockImplementation(() => throw error);
      46 |     const dispatched = await recordSaga(searchSaga, initialAction);

现在,我尝试将其包装在 try/catch 块中:

it("returns an error on a failure", async () => {
    const error = new Error("uh oh!");
    Array.prototype.filter = jest.fn();
    Array.prototype.filter.mockImplementation(() => 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);
    }
  });

这确实通过了,但是,这是一个误报。例如,如果我将预期操作的类型更改为任何废话,测试仍然通过。

我该如何进行这项工作?

编辑: 我注意到console.log(dispatched) 在最后一个传递的示例中从未被激活。我在try 块中添加了该日志语句的副本,并且我看到我am 得到了正确的失败操作返回。

玩弄日志记录,似乎错误被抛出并捕获在一些奇怪的地方。

 it("returns an error on a failure", async () => {
    const error = new Error("uh oh!");
    Array.prototype.filter = jest.fn();
    Array.prototype.filter.mockImplementation(() => 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);
    }
  });

上面记录了 try 块中正确的调度动作,然后记录了 catch 块中的“uh oh”错误。删除 try 块的最后一行会记录 try 块中的正确操作,就是这样,它通过了。当然,它通过了,因为没有断言会失败。

所以它似乎是引发错误的实际断言。我不知道何时抛出错误以及如何避免它。

【问题讨论】:

    标签: javascript redux jestjs


    【解决方案1】:

    如何内联错误抛出:

    it("returns an error on a failure", async () => {
        Array.prototype.filter = jest.fn();
        Array.prototype.filter.mockImplementation(() => throw Error("uh oh!"));
        const dispatched = await recordSaga(searchSaga, initialAction);
        const expectedAction = { type: "CUSTOMER_SEARCH_FAILURE", error };
        console.log(dispatched);
        expect(dispatched).toContainEqual(expectedAction);
      });
    

    【讨论】:

    • 好吧,它从来没有定义过error 变量,所以我添加了const error = new Error("uh oh!"); 让它运行。但是随后实际上抛出了错误,这是我首先遇到的问题(我原来的问题中的第三个 sn-p)。您的代码与该摘录几乎相同。
    猜你喜欢
    • 2020-10-26
    • 2017-12-18
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 2020-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    相关资源
    最近更新 更多