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

ann*_*piv 0 mocking typescript reactjs react-testing-library msw

我测试了一个反应组件,它应该显示旋转器、错误或获取的食谱列表。我设法测试该组件的加载以及何时成功获取数据。我遇到测试错误的问题。我使用 msw 创建了测试服务器,它具有返回错误的路由处理程序。我使用 axios 向服务器发出请求。我认为问题出在这里:axios 发出 3 个请求,直到最后一个响应 useQuery 返回 isLoading=true, isError=false。仅此后才返回 isLoading=false, isError=true。因此,在我的错误测试中, screen.debug() 显示微调器,并且 errorMessage 返回错误,因为它找不到带有文本“error”的渲染元素,该组件应该在发生错误时显示。对此我能做什么?我没有主意了。


编辑:

  • 我发现 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();
    });
  });
});

Run Code Online (Sandbox Code Playgroud)

组件代码:

来自 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} />
      ))}
    </>
  );
};
Run Code Online (Sandbox Code Playgroud)

小智 11

我使用 QueryClient 禁用重试。和 setupServer 来模拟网络连接

    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();
    })
  });
Run Code Online (Sandbox Code Playgroud)