当前位置: 首页 > 知识库问答 >
问题:

使用React查询和axios测试React组件中的错误时出现问题。使用React测试库、Jest、msw进行测试

平嘉熙
2023-03-14

我测试一个反应组件,它应该显示旋转器、错误或获取食谱的列表。我设法测试这个组件的加载和当它成功获得数据。我有一个测试错误的问题。我用msw创建了测试服务器,它具有返回错误的路由处理程序。我使用axios向服务器发出请求。我认为问题就出在这里:axios发出3个请求,直到最后一个响应useQuery返回isLoding=true,isError=false。只有在这之后,它才返回isLoding=false, isError=true。因此,在我的测试错误screen.debug()显示微调器,和错误消息返回错误,因为它没有找到一个呈现的元素与文本错误,该组件应该显示何时发生错误。对此我能做些什么呢?我没有想法了。

编辑:

  • 我发现useQuery中有一个设置,重试,默认为3个请求。我仍然不知道如何在我的测试中处理组件重试请求。

我不熟悉反应测试和打字脚本。

来自RecipeList.test.tsx:

import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { QueryClient, QueryClientProvider, QueryCache } from 'react-query';

import RecipeList from './RecipeList';

const server = setupServer(
  rest.get(`${someUrl}`, (req, res, ctx) =>
    res(ctx.status(200), ctx.json(data))
  )
);

const queryCache = new QueryCache();
const RecipeListWithQueryClient = () => {
  const client = new QueryClient();
  return (
    <QueryClientProvider client={client}>
      <RecipeList />
    </QueryClientProvider>
  );
};

// Tests setup
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
afterEach(() => {
  queryCache.clear();
});

describe('RecipeList', () => {
  //some tests that pass

  describe('while error', () => {
    it('display error message', async () => {
      server.use(
        rest.get(`${someUrl}`, (req, res, ctx) => res(ctx.status(404)))
      );
      render(<RecipeListWithQueryClient />);
      // FOLLOWING CODE RAISE ERROR
      const errorMessage = await screen.findByText(/error/i);
      await expect(errorMessage).toBeInTheDocument();
    });
  });
});

来自RecipeList.tsx:

import { fetchRecipes } from 'api';

const RecipeList: React.FC = () => {
  const { data, isLoading, isError } = useQuery<
    RecipeDataInterface,
    Error
  >('recipes', fetchRecipes);;

  if (isLoading) {
    return (
      <Spinner>
        <span className="sr-only">Loading...</span>
      </Spinner>
    );
  }

  if (isError) {
    return (
      <Alert >Error occured. Please try again later</Alert>
    );
  }

  return (
    <>
      {data?.records.map((recipe: RecipeInterface) => (
        <RecipeItem key={recipe.id} recipe={recipe.fields} />
      ))}
    </>
  );
};

共有2个答案

罗源
2023-03-14

我找到的解决方案是为测试设置单独的超时值。

在RTL for waitFor异步方法中,根据文档:

“默认超时为1000毫秒,这将使您保持Jest的默认超时5000毫秒。”

我必须为RTL异步函数设置超时选项,但这还不够,因为我遇到了一个错误:

"超过5000 ms的测试超时。如果这是一个长时间运行的测试,使用jest.set超时(newTimeout)来增加超时值。"我必须更改Jest为测试设置的超时值。如本评论所述,可以通过两种方式完成:

“1.向it添加第三个参数,即it('运行缓慢',()=

最后,我的测试如下所示:


  it('display error message', async () => {
    server.use(
      rest.get(getUrl('/recipes'), (req, res, ctx) =>
        res(ctx.status(500), ctx.json({ errorMessage: 'Test Error' }))
      )
    );

    render(<RecipeListWithQueryClient />);

    expect(
      await screen.findByText(/error/i, {}, { timeout: 10000 })
    ).toBeInTheDocument();
  }, 10000);

这里可以使用不同的异步方法,如waitFor和waitForElementToBeRemoved,它们都可以将{timeout:10000}对象作为参数。

这个解决方案适合我,但是我想改进它,以避免测试花费太多时间。我只是还不知道怎么做。

夏兴平
2023-03-14

我使用QueryClient禁用重试。和设置服务器到模拟网络连接

    import { QueryClient, QueryClientProvider} from 'react-query';
    import { setupServer } from 'msw/node'
    import { rest } from 'msw'

    
const server = setupServer( 
  rest.get('https://reqres.in/api/users', (req, res, ctx) => {      
      return res(
        ctx.status(200),
        ctx.json(userSuccessResponseJson()
            ),
      )
    }),)

beforeAll(() => server.listen())
afterEach(() => {
  server.resetHandlers();
  queryClient.clear();
})
afterAll(() => server.close())


const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      retryDelay: 1,
      retry:0,
    },
  },
})
const Wrapper = ({ children }) => (
  <QueryClientProvider client={queryClient}>
    {children}
  </QueryClientProvider>
);



  test('Renders Error text when backend server response with error', async () => {
    server.use(
      rest.get('https://reqres.in/api/users', (req, res, ctx) => {
        return res(ctx.status(403))
      })
    );
  
    render(<Wrapper><CompanyList />)</Wrapper>);
  
    const linkElement = screen.getByText(/Loading/i);
    expect(linkElement).toBeInTheDocument();
  
    await waitFor(() => {      
      const fetchedText = screen.getByText(/Error:/i);      
      expect(fetchedText).toBeInTheDocument();
    })
  });
 类似资料:
  • 问题内容: react:16.3.0-alpha.1 jest: “22.3.0” enzyme: 3.3.0 typescript: 2.7.1 码: 测试: 错误: 问题答案: 解: 1:使用异步/等待语法。 2:使用安装座(不浅)。 3:等待异步组件生命周期。 例如:

  • 问题内容: 因此,我正在从基于类的组件转移到功能组件,但在使用jest / zyme编写功能组件内部的方法(显式使用钩子)编写测试时陷入困境。这是我的代码的精简版。 我知道我可以通过导出来编写测试。但是如何测试或方法呢?如果它是基于类的组件,那么我可以将组件变浅,并从实例中将其用作 但这不适用于功能组件,因为无法以这种方式访问​​内部方法。有什么方法可以访问这些方法,还是应该在测试时将功能组件视为

  • 问题内容: 首先,我遵循Flux架构。 我有一个显示秒数的指示器,例如:30秒。每显示一秒,它就会少显示一秒钟,因此29、28、27直到0。当到达0时,我清除间隔,使其不再重复。而且,我触发一个动作。派遣此操作后,我的商店会通知我。因此,发生这种情况时,我将间隔重置为30秒,依此类推。组件看起来像: 组件工作正常。现在,我想用Jest测试它。我知道我可以使用renderIntoDocument,然

  • 我有以下功能。 通过下面的单元测试,我可以点击“dispatch(userRequest());” 然而,我不知道如何测试下面的行和

  • 我是React.js的新手。在试图理解React中的生命周期时,我偶然发现了组件WillReceiveProps。即使我掌握了其他功能,我仍然无法确定组件是否会接收道具。我创建了一个小片段,每次单击按钮时,我都会递增变量“val”。当val变为5的倍数时,我想更改“递增”的值,但我无法这样做。 我的代码是: 有线索吗?提前谢谢

  • 在了解上面的一些React基本概念过后,我们就可以来使用TDD的思想来进行我们开发了。 Create React App默认使用Jest进行测试,所以你需要先安装jest-cli,进入到client根目录: $ npm install jest-cli@20.0.4 --save-dev 注意版本 在安装的时候最好和我这里的版本保持一致,因为其他的版本可能会有其他问题,就需要自己去踩坑了哦~~~

  • 问题内容: App.js App.test.js 这个最小的示例在浏览器中可以正常工作,但是测试失败。我认为没有调用onChange处理程序。如何在测试中触发onChange回调?查找fireEvent元素的首选方法是什么?谢谢 问题答案: 这一定是关于RTL的最常见的问题:D 最好的策略是使用(或测试框架中的等效方法)模拟选择并呈现HTML选择。 有关为什么这是最佳方法的更多信息,我也写了一些适

  • 我是React Native的新手,我安装了React Native,我想使用y设备(Realme 2)进行测试。 使用USB调试,但我卡在这个相同的手机上使用Android Studio在亚行运行。 正在启动JS服务器。。。安装应用程序的信息。。。 配置项目:应用文件C:\用户\Muhammed Sajid Ali.android\repositories.cfg无法加载。在D:\sajid\A