Как использовать __mocks__ в проекте React Native с Jest

Я создаю приложение React Native и пишу свои модульные тесты с помощью Jest.

(Как видно из этот вопрос,) Я пишу функцию, которая проверяет, есть ли сетевое соединение.

Вот функция (checkNetwork.ts):

import { NetInfo } from "react-native";
import { NO_NETWORK_CONNECTION } from "../../../../config/constants/errors";

const checkNetwork = (): Promise<boolean | string> =>
  new Promise((resolve, reject) => {
    NetInfo.isConnected
      .fetch()
      .then(isConnected => (isConnected ? resolve(true) : reject(NO_NETWORK_CONNECTION)))
      .catch(() => reject(NO_NETWORK_CONNECTION));
  });

export default checkNetwork;

Теперь я хочу поиздеваться над этой функцией при тестировании другой функции, которая выполняет вызовы API.

Я создал папку под названием __mocks__ рядом с checkNetwork.ts внутри checkNetwork/ (см. Структуру папок ниже). В нем я также создал еще один файл с именем checkNetwork.ts, который содержит макет и выглядит так:

const checkNetwork = () => new Promise(resolve => resolve(true));

export default checkNetwork;

Функция, которая использует эту функцию, делает простой запрос на выборку (postRequests.ts):

import checkNetwork from "../../core/checkNetwork/checkNetwork";

export const postRequestWithoutHeader = (fullUrlRoute: string, body: object) =>
  checkNetwork().then(() =>
    fetch(fullUrlRoute, {
      method: "POST",
      body: JSON.stringify(body),
      headers: { "Content-Type": "application/json" }
    }).then(response =>
      response.json().then(json => {
        if (!response.ok) {
          return Promise.reject(json);
        }
        return json;
      })
    )
  );

Структура папок выглядит так:

myreactnativeproject
  ├── app/
  │   ├── services/
  │   │   ├── utils/
  │   │   │    └── core/
  │   │   │        └── checkNetwork/
  │   │   │              └── checkNetwork.ts
  │   │   ├── serverRequests/
  │   │   │    └── POST/
  │   │   │        └── postRequests.ts
  │   .   .
  │   .   .
  │   .   .
  .
  .
  .

Затем я создал другой файл под названием postRequests.test.ts в POST/ для написания модульных тестов для postRequests.test.ts. Теперь я ожидал, что Jest автоматически использует макет, который возвращает true. Но на самом деле происходит то, что тест не возвращает NO_NETWORK_CONNECTION. Как я могу заставить Jest использовать макет?

Зод: сила проверки и преобразования данных
Зод: сила проверки и преобразования данных
Сегодня я хочу познакомить вас с библиотекой Zod и раскрыть некоторые ее особенности, например, возможности валидации и трансформации данных, а также...
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Как заставить Remix работать с Mantine и Cloudflare Pages/Workers
Мне нравится библиотека Mantine Component , но заставить ее работать без проблем с Remix бывает непросто.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
TypeScript против JavaScript
TypeScript против JavaScript
TypeScript vs JavaScript - в чем различия и какой из них выбрать?
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Синхронизация localStorage в масштабах всего приложения с помощью пользовательского реактивного хука useLocalStorage
Не все нужно хранить на стороне сервера. Иногда все, что вам нужно, это постоянное хранилище на стороне клиента для хранения уникальных для клиента...
Что такое ленивая загрузка в Angular и как ее применять
Что такое ленивая загрузка в Angular и как ее применять
Ленивая загрузка - это техника, используемая в Angular для повышения производительности приложения путем загрузки модулей только тогда, когда они...
1
0
680
1

Ответы 1

Вот решение, структура папок не имеет значения, для простоты структура папок выглядит следующим образом:

.
├── __mocks__
│   └── checkNetwork.ts
├── checkNetwork.ts
├── errors.ts
├── postRequests.test.ts
└── postRequests.ts

checkNetwork.ts:

import NetInfo from '@react-native-community/netinfo';
import { NO_NETWORK_CONNECTION } from './errors';

const checkNetwork = (): Promise<boolean | string> =>
  new Promise((resolve, reject) => {
    NetInfo.isConnected
      .fetch()
      .then(isConnected => (isConnected ? resolve(true) : reject(NO_NETWORK_CONNECTION)))
      .catch(() => reject(NO_NETWORK_CONNECTION));
  });

export default checkNetwork;

postRequests.ts:

import checkNetwork from './checkNetwork';
import fetch from 'node-fetch';

export const postRequestWithoutHeader = (fullUrlRoute: string, body: object) =>
  checkNetwork().then(() =>
    fetch(fullUrlRoute, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: { 'Content-Type': 'application/json' }
    }).then(response =>
      response.json().then(json => {
        if (!response.ok) {
          return Promise.reject(json);
        }
        return json;
      })
    )
  );

Модульный тест:

postRequests.test.ts:

import { postRequestWithoutHeader } from './postRequests';
import fetch from 'node-fetch';

const { Response } = jest.requireActual('node-fetch');

jest.mock('./checkNetwork.ts');
jest.mock('node-fetch');

describe('postRequestWithoutHeader', () => {
  const mockedData = { data: 'mocked data' };
  const mockedJSONData = JSON.stringify(mockedData);
  const urlRoute = 'https://github.com/mrdulin';
  const body = {};

  it('should post request without header correctly', async () => {
    (fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce(new Response(mockedJSONData));
    const actualValue = await postRequestWithoutHeader(urlRoute, body);
    expect(actualValue).toEqual(mockedData);
    expect(fetch).toBeCalledWith(urlRoute, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: { 'Content-Type': 'application/json' }
    });
  });

  it('should post request error', async () => {
    const mockedResponse = new Response(mockedJSONData, { status: 400 });
    (fetch as jest.MockedFunction<typeof fetch>).mockResolvedValueOnce(mockedResponse);
    await expect(postRequestWithoutHeader(urlRoute, body)).rejects.toEqual(mockedData);
    expect(fetch).toBeCalledWith(urlRoute, {
      method: 'POST',
      body: JSON.stringify(body),
      headers: { 'Content-Type': 'application/json' }
    });
  });
});

Результат модульного тестирования со 100% покрытием:

 PASS  src/stackoverflow/52673113/postRequests.test.ts
  postRequestWithoutHeader
    ✓ should post request without header correctly (7ms)
    ✓ should post request error (1ms)

-----------------|----------|----------|----------|----------|-------------------|
File             |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------------|----------|----------|----------|----------|-------------------|
All files        |      100 |      100 |      100 |      100 |                   |
 postRequests.ts |      100 |      100 |      100 |      100 |                   |
-----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.996s, estimated 5s

Вот завершенная демонстрация: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/52673113

Зависимости:

"@react-native-community/netinfo": "^4.2.1",
"react-native": "^0.60.5",

Я использую модуль react-native последней версии, поэтому модуль NetInfo устарел. https://facebook.github.io/react-native/docs/netinfo.html

Другие вопросы по теме