Как мне проверить, получил ли я все данные из get-запроса в библиотеке jest

#reactjs #axios #jestjs #react-hooks #react-testing-library

Вопрос:

моя проблема
Я хочу написать тест (с библиотекой тестирования реакции и шуткой), чтобы убедиться, что мой запрос get получает список json-объектов (длиной > 400).>
Код для этого представлен ниже.
Проблема в том, что я получаю сообщение об ошибке: «Время ожидания истекло».
Что я делаю не так?, Я благодарен за любую помощь и/или руководство.

 import React {useEffect, useState} from 'react';
import Axios from 'axios';

const TestComp = () => {

const [data, setData] = useState([]);
useEffect(()=>{
    Axios.get("/../someURL").then((res) => {
        setData(res.data);
    })
});

return (
    <table>
        {state.data.map(d => (
            <tr>
                <th>
                    {data.req_id}
                </th>
            </tr>
        ))}
    </table>
  );
};
 
 import React from 'react';
import {render, screen, waitFor} from '@testing-library/react';
import TestComp from "./../TestComp";

test("test", async () => {
    render(<TestComp/>);
    await waitFor(async() => {
        const receivedRows = await screen.findAllByRole("row"); 
        const nrOfReceivedRows = receivedRows.length;
        expect(nrOfReceivedRows > 400).toBeTruthy();
        // I have also tried expect(nrOfReceivedRows).toBeGreaterThan(400);
    });
})
 

Комментарии:

1. Вы делаете реальный запрос в тесте для TestComp и, если да, то почему?

2. Да, точно, это реальный запрос, я новичок в тестировании, и я подумал, что было бы разумно сделать реальный запрос, потому что тогда я смогу знать (всякий раз, когда я буду запускать тест), не работает ли серверная часть или интерфейс.

3. @jonrsharpe , возможно, я думаю об этом неправильно?

4. Я бы так сказал, потому что прямо сейчас тест проваливается, и вы не можете сказать, в чем проблема-в бэкэнде или в интерфейсе. Кроме того, реальные сетевые запросы, как правило, на порядки медленнее, чем вы ожидаете от тестов на уровне модулей. Я бы рекомендовал провести тесты E2E, которые проверяют, что все работает вместе, но на этом уровне вам, вероятно, следует подумать о насмешках на сетевом уровне (например msw ) или о том, чтобы создать фасад вокруг Axios, который вы можете создать сами. Я написал о тестировании приложений React таким образом в своем блоге: blog.jonrshar.pe/2021/Apr/10/js-tdd-api.html

Ответ №1:

В вашем коде есть некоторые проблемы:

  1. <tr> не может появиться в качестве ребенка <table> . Добавьте a <tbody> <thead> или <tfoot> в свой код , чтобы он соответствовал дереву DOM, созданному браузером.
  2. findBy методы представляют собой комбинацию getBy запросов и waitFor . Они принимают waitFor варианты в качестве последнего аргумента (например await screen.findByText('text', queryOptions, waitForOptions) ). Вам не нужно использовать waitFor и findBy запрашивать вместе. См. Раздел Поисковые запросы
  3. Для модульного тестирования вы НЕ должны вызывать реальную внешнюю службу, такую как (вызов API, запрос бд и т. Д.). Эти услуги с побочными эффектами должны быть высмеяны или заглушены. Таким образом, ваши тесты могут выполняться в изолированной среде, не полагаясь на внешние реальные службы. Тест, который вызывает реальную службу, должен быть тестом E2E.

Таким образом, пример модульного теста используется jest.spyOn() для axios.get моделирования метода и его разрешенного/отклоненного значения.

TestComp.jsx :

 import React, { useEffect, useState } from 'react';
import Axios from 'axios';

export const TestComp = () => {
  const [data, setData] = useState([]);
  useEffect(() => {
    Axios.get('/../someURL').then((res) => {
      console.log(res);
      setData(res.data);
    });
  }, []);

  return (
    <table>
      <tbody>
        {data.map((d) => (
          <tr key={d.req_id}>
            <th>{d.req_id}</th>
          </tr>
        ))}
      </tbody>
    </table>
  );
};
 

TestComp.test.jsx :

 import React from 'react';
import Axios from 'axios';
import { render, screen } from '@testing-library/react';
import { TestComp } from './TestComp';

test('test', async () => {
  const getSpy = jest.spyOn(Axios, 'get').mockResolvedValueOnce({
    data: Array(401)
      .fill()
      .map((d, idx) => ({ req_id: idx })),
  });
  render(<TestComp />);
  const receivedRows = await screen.findAllByRole('row');
  expect(receivedRows.length > 400).toBeTruthy();
  getSpy.mockRestore();
});
 

результат теста:

   console.log
    {
      data: [
        { req_id: 0 },  { req_id: 1 },  { req_id: 2 },  { req_id: 3 },
        { req_id: 4 },  { req_id: 5 },  { req_id: 6 },  { req_id: 7 },
        { req_id: 8 },  { req_id: 9 },  { req_id: 10 }, { req_id: 11 },
        { req_id: 12 }, { req_id: 13 }, { req_id: 14 }, { req_id: 15 },
        { req_id: 16 }, { req_id: 17 }, { req_id: 18 }, { req_id: 19 },
        { req_id: 20 }, { req_id: 21 }, { req_id: 22 }, { req_id: 23 },
        { req_id: 24 }, { req_id: 25 }, { req_id: 26 }, { req_id: 27 },
        { req_id: 28 }, { req_id: 29 }, { req_id: 30 }, { req_id: 31 },
        { req_id: 32 }, { req_id: 33 }, { req_id: 34 }, { req_id: 35 },
        { req_id: 36 }, { req_id: 37 }, { req_id: 38 }, { req_id: 39 },
        { req_id: 40 }, { req_id: 41 }, { req_id: 42 }, { req_id: 43 },
        { req_id: 44 }, { req_id: 45 }, { req_id: 46 }, { req_id: 47 },
        { req_id: 48 }, { req_id: 49 }, { req_id: 50 }, { req_id: 51 },
        { req_id: 52 }, { req_id: 53 }, { req_id: 54 }, { req_id: 55 },
        { req_id: 56 }, { req_id: 57 }, { req_id: 58 }, { req_id: 59 },
        { req_id: 60 }, { req_id: 61 }, { req_id: 62 }, { req_id: 63 },
        { req_id: 64 }, { req_id: 65 }, { req_id: 66 }, { req_id: 67 },
        { req_id: 68 }, { req_id: 69 }, { req_id: 70 }, { req_id: 71 },
        { req_id: 72 }, { req_id: 73 }, { req_id: 74 }, { req_id: 75 },
        { req_id: 76 }, { req_id: 77 }, { req_id: 78 }, { req_id: 79 },
        { req_id: 80 }, { req_id: 81 }, { req_id: 82 }, { req_id: 83 },
        { req_id: 84 }, { req_id: 85 }, { req_id: 86 }, { req_id: 87 },
        { req_id: 88 }, { req_id: 89 }, { req_id: 90 }, { req_id: 91 },
        { req_id: 92 }, { req_id: 93 }, { req_id: 94 }, { req_id: 95 },
        { req_id: 96 }, { req_id: 97 }, { req_id: 98 }, { req_id: 99 },
        ... 301 more items
      ]
    }

      at examples/68312820/TestComp.jsx:8:15

 PASS  examples/68312820/TestComp.test.jsx (9.507 s)
  ✓ test (799 ms)

--------------|---------|----------|---------|---------|-------------------
File          | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
--------------|---------|----------|---------|---------|-------------------
All files     |     100 |      100 |     100 |     100 |                   
 TestComp.jsx |     100 |      100 |     100 |     100 |                   
--------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.181 s