Почему в моем шуточном тесте не вызывается client.query?

издеваюсь над крюком Аполлона

jest.mock("@apollo/client", () => ({
  ...jest.requireActual("@apollo/client"),
  useApolloClient: () => ({
    query: jest.fn().mockResolvedValueOnce({
      data: { myReturnValue: { some: "data" } },
      loading: false,
      errors: undefined,
    }),
  }),
}))

моя функция

  const myFunction = (input) => {
    console.info("called this?") // this 100% gets called in the test
    const data = { ...defaultData, ...input }

    return client
      .query({
        query: Query,
        fetchPolicy: "network-only",
        variables: {},
      })
      .then(({ data, errors }) => {
        if (!data?) {
          alert(errors)
        } else {
          console.info("in else block") // this 100% gets called in the test
          runFunction()
        }
      })
  }

в моем тесте регистрируется: «в блоке else»

и в моем тесте у меня есть:

fireEvent.click(screen.getByText("My Button Text"))
await waitFor(() => expect(useApolloClient().query).toBeCalledTimes(1))

В тестовом выводе я получаю

Expected number of calls: 1
Received number of calls: 0

почему это? Он определенно звонил client.query, как это было в журналах

Каждый раз, когда вы вызываете useApolloClient, вы получаете новый объект с новым свойством запроса и новым значением фиктивной функции. expect(useApolloClient().query).toBeCalledTimes(1) никогда не сможет добиться успеха, даже если вы проведете опрос, потому что единственная существующая ссылка на макет находится в ожидании.

jonrsharpe 16.04.2024 13:05

@jonrsharpe спасибо за хорошее объяснение. Есть ли способ достичь того, чего я пытаюсь, или это выходит за рамки модульного теста?

Red Baron 16.04.2024 13:21

Не издевайтесь так. Используйте настоящий экземпляр клиента Apollo.

phry 16.04.2024 13:29

Самое простое решение — не создавать каждый раз новый объект, например. useApolloClient: () => ({ -> useApolloClient: jest.fn().mockReturnValue({ или просто извлеките значение и получите useApolloClient: () => fakeClient. Но, вероятно, существуют и другие подходы, которые помогут вам приблизиться к тестированию реального поведения.

jonrsharpe 16.04.2024 13:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как сказал @phry, не издевайтесь над модулем @apollo/client. Вместо этого следуйте руководству Тестирование компонентов React.

Тестирование компонента с точки зрения пользователя, что эквивалентно тесту черного ящика. Не тестируйте конкретную реализацию (например, expect(someMethod).toBeCalled()). Вместо этого мы должны утверждать, что отображает компонент. После того, как пользователь взаимодействует с компонентом, изменения в содержимом рендеринга будут

например

index.tsx:

import React, { useState } from 'react';
import { gql, useApolloClient } from '@apollo/client';

export const GET_DOG_QUERY = gql`
  query GetDog($name: String) {
    dog(name: $name) {
      id
      name
      breed
    }
  }
`;

export function SomeComponent() {
  const client = useApolloClient();

  const [data, setData] = useState();
  console.info("🚀 ~ SomeComponent ~ data:", data)

  const onClick = () => {
    client
      .query({
        query: GET_DOG_QUERY,
        fetchPolicy: 'network-only',
        variables: {
          name: 'Buck',
        },
      })
      .then(({ data, errors }) => {
        setData(data);
      });
  };

  return (
    <div>
      <button onClick = {onClick}>My Button Text</button>
      {data && <span>{data.dog.breed}</span>}
    </div>
  );
}

index.test.tsx:

import React from 'react';
import { MockedProvider } from '@apollo/client/testing';
import { GET_DOG_QUERY, SomeComponent } from '.';
import { fireEvent, render, screen } from '@testing-library/react';
import '@testing-library/jest-dom';

describe('78333569', () => {
  test('should pass', async () => {
    const mocks = [
      {
        request: {
          query: GET_DOG_QUERY,
          variables: {
            name: 'Buck',
          },
        },
        result: {
          data: {
            dog: { id: '1', name: 'Buck', breed: 'bulldog' },
          },
        },
      },
    ];

    render(
      <MockedProvider mocks = {mocks} addTypename = {false}>
        <SomeComponent />
      </MockedProvider>,
    );

    fireEvent.click(screen.getByText('My Button Text'));
    expect(await screen.findByText('bulldog')).toBeInTheDocument();
  });
});

Результат испытаний:


  console.info
    🚀 ~ SomeComponent ~ data: undefined

      at log (stackoverflow/78333569/index.tsx:18:11)

  console.info
    🚀 ~ SomeComponent ~ data: { dog: { id: '1', name: 'Buck', breed: 'bulldog' } }

      at log (stackoverflow/78333569/index.tsx:18:11)

 PASS  stackoverflow/78333569/index.test.tsx
  78333569
    √ should pass (78 ms)                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                     
Test Suites: 1 passed, 1 total                                                                                                                                                                                                                       
Tests:       1 passed, 1 total                                                                                                                                                                                                                       
Snapshots:   0 total
Time:        1.332 s, estimated 3 s
Ran all test suites related to changed files.

версии пакета:

"@apollo/client": "^3.9.11"

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