通过 jest mock 测试 catch 块

Posted

技术标签:

【中文标题】通过 jest mock 测试 catch 块【英文标题】:Testing catch block via jest mock 【发布时间】:2017-07-15 08:07:01 【问题描述】:

我正在尝试通过 jest 测试异步 redux 操作的“catch”块,但是在模拟中抛出一个 catch 会导致整个测试失败。

我的操作如下:

export function loginUser(username, password) 
  return async dispatch => 
    dispatch(type: UPDATE_IN_PROGRESS);
    try 
      let response = await MyRequest.postAsync(
        '/login', username: username, password: password
      );
      dispatch(
        type: USER_AUTHENTICATED,
        username: response.username,
        token: response.token,
        role: response.role,
        id: response.id
      );
     catch (error) 
      dispatch(type: USER_SIGNED_OUT);
      throw error;
     finally 
      dispatch(type: UPDATE_COMPLETE);
    
  ;

测试试图模拟“MyRequest.postAsync”以引发错误并因此触发 catch 块,但测试只是退出并显示“失败”消息

it('calls expected actions when failed log in', async() => 
  MyRequest.postAsync = jest.fn(() => 
    throw 'error';
  );

  let expectedActions = [
    type: UPDATE_IN_PROGRESS,
    type: USER_SIGNED_OUT,
    type: UPDATE_COMPLETE
  ];

  await store.dispatch(userActions.loginUser('foo', 'bar'));
  expect(store.getActions()).toEqual(expectedActions);
);

有没有办法通过一个笑话模拟函数(或任何其他方式)触发 catch 块在我的测试中执行?无法测试大量代码会很烦人(因为我所有的请求都以相同的方式工作)。

在此先感谢您的帮助。

【问题讨论】:

给你用jest.mock模拟MyRequest,否则不行 对不起@AndreasKöberle 你能稍微详细说明一下吗?使用 jest.fn() 似乎可以很好地模拟导入模块上的函数,这是导致问题的throw 'error' 可能是catch块中的throw 【参考方案1】:

我将我们将在测试函数中访问的实例变量设置为未定义,以便它将进入 catch 块。

PS : 这可能不可能一直存在,因为我们可能不会一直有变量

class APIStore 

 async fetchProductsAPI() 
    try 
       const products =  networkManager.fetch('products')
       this.productsStore.setProducts(prodcuts)
     
    catch(e) 
       this.apiStatus = API_FAILED
       this.apiError = e
    
  

测试用例

it('Check API Error ', async () => 

    const toCheckErrorStore = new APIStore()

    // Setting products store to undefined so that execution goes to catch block
    toCheckErrorStore.productsStore = undefined

    await toCheckErrorStore.fetchProductsAPI()

    expect(toCheckErrorStore.apiStatus).toBe(API_FAILED)
    expect(toCheckErrorStore.apiError).toEqual(errorObjectIWantToCompareWith)

【讨论】:

【参考方案2】:

我不知道它是否仍然相关,但你可以这样做:

it('tests error with async/await', async () => 
  expect.assertions(1);
  try 
    await store.dispatch(userActions.loginUser('foo', 'bar'));
   catch (e) 
    expect(e).toEqual(
      error: 'error',
    );
  
);

这是一个关于错误处理的documentation

【讨论】:

【参考方案3】:

我有同样的问题。对我来说,以下工作。用try/catch 结束等待

  it('calls expected actions when failed log in', async() => 
  MyRequest.postAsync = jest.fn(() => 
    throw 'error';
  );

  let expectedActions = [
    type: UPDATE_IN_PROGRESS,
    type: USER_SIGNED_OUT,
    type: UPDATE_COMPLETE
  ];
  try 
     await store.dispatch(userActions.loginUser('foo', 'bar'));
   catch(e) 
     expect(store.getActions()).toEqual(expectedActions);
  

);

【讨论】:

以上是关于通过 jest mock 测试 catch 块的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jest 在 javascript 中测试 try catch 代码并在 express 中包含带有中间件的 next() 调用?

「CI集成」基于Jest Mock API对业务逻辑集成测试附源码

运行测试时出错 - jest.mock 不是函数

如何使用 jest.mock 模拟 useRef 和反应测试库

前端测试框架Jest系列教程 -- Mock Functions

前端自动化测试框架Jest中的Mock