【问题标题】:Setting value for React context values with React testing library使用 React 测试库设置 React 上下文值
【发布时间】:2021-10-05 01:48:57
【问题描述】:

我正在使用 react-testing-library 测试组件。该组件有一个警报,它接受来自上下文的道具来确定警报是否打开。

const PersonRecord = () => {

  const {
    personSuccessAlert,
    setPersonSuccessAlert,
    updatePersonSuccessAlert,
    setUpdatePersonSuccessAlert,
  } = useContext(PeopleContext);

  return (
      {personSuccessAlert && (
        <div className="person-alert-container">
          <Alert
            ariaLabel="person-create-success-alert"
            icon="success"
            open={personSuccessAlert}
          />
        </div>
      )}
   )
 }

所以上面的代码使用上下文从PeopleContext 中提取personSuccessAlert 的值。如果personSuccessAlert 为真,则会显示警报。我的上下文文件设置如下:

import React, { createContext, useState } from 'react';

export const PeopleContext = createContext();

const PeopleContextProvider = ({ children }) => {
  const [personSuccessAlert, setPersonSuccessAlert] = useState(false);
  const [updatePersonSuccessAlert, setUpdatePersonSuccessAlert] = useState(
    false,
  );

  return (
    <PeopleContext.Provider
      value={{
        personSuccessAlert,
        updatePersonSuccessAlert,
        setPersonSuccessAlert,
        setUpdatePersonSuccessAlert,
      }}>
      {children}
    </PeopleContext.Provider>
  );
};

export default PeopleContextProvider;

现在我正在尝试开发一个将personSuccessAlert = true 传递给PersonRecord 组件的测试。

这是我一直在尝试的:

export function renderWithEmptyPerson(
  ui,
  {
    providerProps,
    path = '/',
    route = '/',
    history = createMemoryHistory({ initialEntries: [route] }),
  },
) {
  return {
    ...render(
      <MockedProvider mocks={getEmptyPerson} addTypename={false}>
        <PeopleContextProvider {...providerProps}>
          <Router history={history}>
            <Route path={path} component={ui} />
          </Router>
        </PeopleContextProvider>
      </MockedProvider>,
    ),
  };
}

describe('empty person record rendering', () => {
  afterEach(cleanup);
  test('empty person', async () => {

    const providerProps = { value: true };

    const { getByText, queryByText, queryByLabelText } = renderWithEmptyPerson(
      PersonRecord,
      {
        providerProps,
        route: 'people/6d6ed1f4-8294-44de-9855-2999bdf9e3a7',
        path: 'people/:slug',
      },
    );
    expect(getByText('Loading...')).toBeInTheDocument();
  });
});

我尝试了const providerProps = { value: true }; 的不同变体。将 value 替换为 personSuccessAlert 无效。

感谢任何建议或帮助。

【问题讨论】:

    标签: reactjs react-hooks react-testing-library


    【解决方案1】:

    您将providerProps 传递给PeopleContextProvider,但PeopleContextProvider 没有对道具做任何事情。您需要实际使用这些道具,例如设置初始状态。您可以尝试以下方法:

    const PeopleContextProvider = ({ children, initialPersonSuccessAlert = false }) => {
      const [personSuccessAlert, setPersonSuccessAlert] = useState(initialPersonSuccessAlert);
      const [updatePersonSuccessAlert, setUpdatePersonSuccessAlert] = useState(
        false,
      );
    
      return (
        <PeopleContext.Provider
          value={{
            personSuccessAlert,
            updatePersonSuccessAlert,
            setPersonSuccessAlert,
            setUpdatePersonSuccessAlert,
          }}>
          {children}
        </PeopleContext.Provider>
      );
    };
    

    这将允许您通过传入 initialPersonSuccessAlert 属性来设置 personSuccessAlert 的初始状态。您可以像这样更新您的测试:

    const providerProps = { initialPersonSuccessAlert: true };
    

    或者,如果您只想在测试文件中进行更改,您可以考虑更新 renderWithEmptyPerson 函数以直接使用 PeopleContext.Provider 而不是 PeopleContextProvider 组件。这将允许您根据需要设置上下文值。

    【讨论】:

    • 嗯,我认为这可能有效,但它需要我更改我的实际代码,而不仅仅是我的测试。我希望有一些方法可以在我的测试套件中模拟 personSuccessAlert 的价值。
    • 如果您执意不修改代码,那么您可以考虑更新renderWithEmptyPerson 函数以直接使用PeopleContext.Provider 而不是PeopleContextProvider 组件。这将允许您随意设置上下文value。除了嘲笑PeopleContextProvider、useContext 或useState 之外,没有其他好的方法可以做到这一点,我强烈不推荐所有这些,因为它会使你的测试变得非常脆弱。
    猜你喜欢
    • 1970-01-01
    • 2017-06-03
    • 1970-01-01
    • 2021-07-08
    • 2019-12-31
    • 2020-03-24
    • 2021-07-03
    • 1970-01-01
    • 2020-11-11
    相关资源
    最近更新 更多