使用 renderHook 测试自定义钩子

Yon*_*Nir 5 reactjs react-redux react-hooks react-hooks-testing-library

我想测试一个自定义钩子,该钩子是作为帮助函数实现的,以便与其他钩子重用代码。它正在调用useDispatchuseSelector在其实现中,以及将数据保存在会话存储中:

 export function useCustomHook(key, obj)
  {
    let myObject = {
      somefield: obj.someField
    };
    sessionStorage.setItem(key, JSON.stringify(myObject));
    const dispatch = useDispatch();
    dispatch(actionCreator.addAction(key, myObject));
  }
Run Code Online (Sandbox Code Playgroud)

和测试:

it('should have data in redux and session storage', () =>
{
  const obj = { 
    somefield: 'my val', 
  };
  renderHook(() => useCustomHook('some key', obj));
  let savedObj= JSON.parse(sessionStorage.getItem('some key'));
  expect(savedObj.someField).toBe('my val');
  renderHook(() => 
  {
    console.log("INSIDE");
    let reduxObj = useSelector(state => state.vals);
    console.log("THE OBJECT: " );
    console.log(reduxObj);
    expect(reduxObj).toBe(2); //just to see if it fails the test - it's not
  });
})
Run Code Online (Sandbox Code Playgroud)

无论我尝试什么,测试都只会到达“INSIDE”控制台日志,而不会打印“THE OBJECT:”控制台日志。测试本身仍然通过,所以就像以useSelector某种方式停止了 renderHook 执行的其余部分。

我猜这与测试没有连接存储有关......在这种情况下可以做什么来测试 redux?

Mic*_*per 1

您需要提供一个wrapper组件来添加 reduxProviderstore连接到:

it('should have data in redux and session storage', () =>
{
  const obj = { 
    somefield: 'my val', 
  };

  const store = {} // create/mock a store
  const wrapper = ({ children }) => <Provider store={store}>{children}</Provider>

  renderHook(() => useCustomHook('some key', obj), { wrapper });
  let savedObj= JSON.parse(sessionStorage.getItem('some key'));
  expect(savedObj.someField).toBe('my val');
  renderHook(() => {
    console.log("INSIDE");
    let reduxObj = useSelector(state => state.vals);
    console.log("THE OBJECT: " );
    console.log(reduxObj);
    expect(reduxObj).toBe(2); //just to see if it fails the test - it's not
  }, { wrapper });
})
Run Code Online (Sandbox Code Playgroud)

顺便说一句,renderHook正在捕获错误,这就是为什么您在测试中看不到它们,如果您尝试访问result.current它就会抛出错误,并且您可能已经看到它在 中表示result.error,但是这里的用法不从要断言的自定义挂钩返回值是很不寻常的。

这也可能会因为在第二次调用中包含断言而给您带来问题renderHook。您可能想要从钩子返回值并在外部断言,或者在 redux 存储中断言更新后的值。