首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反应本机测试-不等待行动

反应本机测试-不等待行动
EN

Stack Overflow用户
提问于 2020-11-22 09:17:07
回答 2查看 5.3K关注 0票数 14

下面的测试是通过的,但我收到了以下两次警告,我不知道为什么。有人能帮我弄清楚吗?

代码语言:javascript
复制
    console.error
    Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);
      at printWarning (../../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:120:30)
      at error (../../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:92:5)
      at ../../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:14953:13
      at tryCallOne (../../node_modules/react-native/node_modules/promise/lib/core.js:37:12)
      at ../../node_modules/react-native/node_modules/promise/lib/core.js:123:15
      at flush (../../node_modules/asap/raw.js:50:29)
代码语言:javascript
复制
import { fireEvent } from '@testing-library/react-native'
import { renderScreen } from 'test/render'

describe('screens/home', () => {
  it('should render and redirect to the EventScreen', async () => {
    const {
      getByA11yLabel,
      findByA11yLabel,
      findAllByA11yLabel,
      toJSON
    } = renderScreen('Main')
    expect(toJSON()).toMatchSnapshot('Default render')

    const title = 'New event'
    const titleInput = getByA11yLabel('event.title')

    // Change title - sync fn
    fireEvent.changeText(titleInput, title)

    // Create button should be visible
    const createButton = await findByA11yLabel('event.create')
    expect(titleInput.props.value).toBe(title)
    expect(createButton).toBeTruthy()
    expect(toJSON()).toMatchSnapshot('Change title')

    // Create event - async fn
    fireEvent.press(createButton)

    // The app should be redirected to the EventScreen
    const titleInputs = await findAllByA11yLabel('event.title')
    const upsertButton = await findByA11yLabel('event.upsert')
    expect(toJSON()).toMatchSnapshot('Create event')
    expect(titleInputs).toHaveLength(2)
    expect(titleInputs[0].props.value).toBe('') // @MainScreen
    expect(titleInputs[1].props.value).toBe(title) // @EventScreen
    expect(upsertButton).toBeTruthy()
  })
})

依赖关系:

  • 反应: 16.13.1
  • 世博会: 39.0.4
  • 笑话: 26.6.3
  • ts-玩笑: 26.4.4
  • jest-博览会: 39.0.0
  • @jest library/jest-本机: 3.4.3
  • @react库/react: 11.2.2
  • @测试-库/反应-本机: 7.1.0
  • 反应-测试-渲染器: 16.13.1
  • 打字本: 4.1.2
EN

回答 2

Stack Overflow用户

发布于 2021-09-16 02:58:13

如果您已经用尽了所有其他调试工作,并且非常肯定您的代码编写正确,那么它可能与用react-native/jest-preset替换global.Promise (参见问题)有关。

在这种情况下,问题的解决方案是覆盖/修补jest预置,以首先保存原始的全局承诺,应用react-native/jest-preset,然后恢复原始承诺(覆盖模拟版本)。这允许我在与呈现无关的测试中使用await,而不会触发可怕的

代码语言:javascript
复制
console.error
Warning: You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);

此片段展示了执行此修补程序的一种方法:await/commit/64a76486f31bdc41f5c240d28263285683755938

票数 4
EN

Stack Overflow用户

发布于 2020-11-25 02:18:27

我也面临着同样的问题。在我的案例中,我在组件中使用了useEffect。在进行测试时,它促使我将呈现包装在一个act()调用中。一旦我这样做,即act(async () => ...),我的初始问题就解决了,但是我得到了上面提到的错误(Warning: You called act(async () => ...) without await.)。我必须在我的测试中使用await act(async () => ...)来解决这个问题。虽然我仍然不知道为什么要这样做。

作为参考,我将使用await act(async () => ...);添加一个完整的示例组件和相应的测试

LocationComponent.tsx

代码语言:javascript
复制
/** @jsx jsx */
import { jsx } from 'theme-ui';
import { FunctionComponent, useEffect, useState } from 'react';

type Coordinate = {
  latitude: number;
  longitude: number;
};

const LocationComponent: FunctionComponent<any> = () => {
  const [coordinate, setCoordinate] = useState<Coordinate>();
  const [sharedLocation, setSharedLocation] = useState<boolean>();
  useEffect(() => {
    let mounted = true;

    if (!coordinate && navigator) {
      navigator.geolocation.getCurrentPosition(function (position) {
        setCoordinate({
          latitude: position.coords.latitude,
          longitude: position.coords.longitude,
        });
      });
      navigator.permissions
        .query({ name: 'geolocation' })
        .then(function (result) {
          if (mounted) setSharedLocation(result.state === 'granted');
        });
    }

    return () => (mounted = false);
  });

  return (
    <>
      <div>Location shared:{sharedLocation ? 'Yes' : 'No'}</div>
      <div>Latitude:{coordinate?.latitude}</div>
      <div>Longitude:{coordinate?.longitude}</div>
    </>
  );
};
export default LocationComponent;

LocationComponent.spec.tsx

代码语言:javascript
复制
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import LocationComponent from '../../../../../src/components/scheduler/location/LocationComponent';

const TEST_COORDS = {
  latitude: 41.8817089,
  longitude: -87.643301,
};

global.navigator.permissions = {
  query: jest
    .fn()
    .mockImplementationOnce(() => Promise.resolve({ state: 'granted' })),
};

global.navigator.geolocation = {
  getCurrentPosition: jest.fn().mockImplementationOnce((success) =>
    Promise.resolve(
      success({
        coords: TEST_COORDS,
      })
    )
  ),
};

describe("Location Component when location share is 'granted'", () => {
  it('should display current location details', async () => {
    await act(async () => {
      const { getByText } = render(<LocationComponent />);

      /*expect(
        await waitFor(() => getByText('Location shared:Yes'))
      ).toBeInTheDocument();*/
      expect(
        await waitFor(() => getByText('Latitude:41.8817089'))
      ).toBeInTheDocument();
      expect(
        await waitFor(() => getByText('Longitude:-87.643301'))
      ).toBeInTheDocument();
    });
  });
});
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64952449

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档