繁体   English   中英

React 测试库单元测试用例:无法在未安装的组件上找到节点

[英]React Testing Library Unit Test Case: Unable to find node on an unmounted component

我遇到了 React Unit 测试用例的问题。

反应:v18.2 节点 v18.8

创建自定义 function 以使用 ReactIntl 渲染组件。 如果我们在两个不同的测试用例中使用同一文件中的自定义组件,则第二个测试失败并出现以下错误。

Unable to find node on an unmounted component.

at findCurrentFiberUsingSlowPath (node_modules/react-dom/cjs/react-dom.development.js:4552:13)
at findCurrentHostFiber (node_modules/react-dom/cjs/react-dom.development.js:4703:23)
at findHostInstanceWithWarning (node_modules/react-dom/cjs/react-dom.development.js:28745:21)
at Object.findDOMNode (node_modules/react-dom/cjs/react-dom.development.js:29645:12)
at Transition.performEnter (node_modules/react-transition-group/cjs/Transition.js:280:71)
at node_modules/react-transition-group/cjs/Transition.js:259:27

如果我使用 setTimeout 在不同的文件或测试用例中运行,它会按预期工作并且没有错误。 请在下面找到其他配置。 即使它是相同的测试用例,它也失败了。

setUpIntlConfig();
beforeAll(() => server.listen());

afterEach(() => {
  server.resetHandlers();
});

afterAll(() => {
  jest.clearAllMocks();
  server.close();
  cleanup();
});

国际配置:

export const setUpIntlConfig = () => {
  if (global.Intl) {
    Intl.NumberFormat = IntlPolyfill.NumberFormat;
    Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat;
  } else {
    global.Intl = IntlPolyfill;
  }
};

export const RenderWithReactIntl = (component: any) => {
  return {
    ...render(
      <IntlProvider locale="en" messages={en}>
        {component}
      </IntlProvider>
    )
  };
};

我使用 msw 作为模拟服务器。 如果我们缺少任何配置,请指导我们。

测试用例:

test('fire get resource details with data', async () => {
    jest.spyOn(SGWidgets, 'getAuthorizationHeader').mockReturnValue('test-access-token');

    process.env = Object.assign(process.env, { REACT_APP_DIAM_API_ENDPOINT: '' });

    RenderWithReactIntl(<AllocatedAccess diamUserId={diamUserIdWithData} />);
    await waitForElementToBeRemoved(() => screen.getByText(/loading data.../i));

    const viewResource = screen.getAllByText(/view resource/i);
    fireEvent.click(viewResource[0]);
    await waitForElementToBeRemoved(() => screen.getByText(/loading/i));

    const ownerName = screen.getByText(/benedicte masson/i);

    expect(ownerName).toBeInTheDocument();
  });
  
   test('fire get resource details with data----2', async () => {
    jest.spyOn(SGWidgets, 'getAuthorizationHeader').mockReturnValue('test-access-token');

    process.env = Object.assign(process.env, { REACT_APP_DIAM_API_ENDPOINT: '' });

    RenderWithReactIntl(<AllocatedAccess diamUserId={diamUserIdWithData} />);
    await waitForElementToBeRemoved(() => screen.getByText(/loading data.../i));

    const viewResource = screen.getAllByText(/view resource/i);
    fireEvent.click(viewResource[0]);
    await waitForElementToBeRemoved(() => screen.getByText(/loading/i));

    const ownerName = screen.getByText(/benedicte masson/i);

    expect(ownerName).toBeInTheDocument();
  });

您可以尝试以下更改:

test('fire get resource details with data----2', async () => {
  jest.spyOn(SGWidgets, 'getAuthorizationHeader').mockReturnValue('test-access-token');

  process.env = Object.assign(process.env, { REACT_APP_DIAM_API_ENDPOINT: '' });

  RenderWithReactIntl(<AllocatedAccess diamUserId={diamUserIdWithData} />);
  await waitFor(() => expect(screen.getByText(/loading data.../i)).not.toBeInTheDocument());

  const viewResource = screen.getAllByText(/view resource/i);

  act(() => {
    fireEvent.click(viewResource[0]);
  });

  await waitFor(() => expect(screen.getByText(/loading/i)).not.toBeInTheDocument());

  expect(screen.getByText(/benedicte masson/i)).toBeVisible();
});

在更改屏幕上可见的内容时,我已经养成了使用act()的习惯。 一个很好的指南: https://testing-library.com/docs/guide-disappearance/

不过,在上面的 waitFor() 块中使用 getBy* 可能会更好地专门检查文本的不存在。

如果没有看到您的代码,很难进一步 go 。 我总是说保持测试简短而简单,我们正在测试一件事。 他们越复杂,对不可预见的错误所做的更改就越多。 看起来您正在渲染,等待模态关闭,然后单击,然后是另一个模态关闭,然后屏幕上出现更多文本。 我会把它分成两个或更多的测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM