JavaRush /Курсы /Модуль 5. Spring /Лекция 297: Тестирование GraphQL API

Лекция 297: Тестирование GraphQL API

Модуль 5. Spring
30 уровень , 6 лекция
Открыта

Любой разработчик знает, что чем меньше в API багов, тем меньше звонков в техподдержку. Тестирование — это не просто проверка работоспособности вашей системы, это способ доказать, что она работает так, как задумано. Тестирование GraphQL API особенно важно:

  • Проверка логики запросов и мутаций: убедиться, что ваши запросы выполняются корректно, а мутации изменяют данные так, как нужно.
  • Обеспечение безопасности: проверить, что пользователи имеют доступ только к тем данным, к которым они должны иметь доступ.
  • Производительность: убедиться, что API обрабатывает запросы быстро и эффективно даже под нагрузкой.
  • Стабильность: гарантировать, что изменения в коде не ломают уже существующий функционал.

Подходы к тестированию GraphQL API

Как и в любом приложении, тестирование GraphQL API можно разделить на несколько уровней:

Unit-тесты

Это тесты отдельных компонентов приложения, таких как Data Fetchers, Resolvers, или сервисы. Цель — проверить их изолированно от других компонентов.

Пример:


@Test
void testFetchUserById() {
    // Given
    UUID userId = UUID.randomUUID();
    User mockUser = new User(userId, "John", "Doe");
    when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));

    // When
    User result = userService.fetchUserById(userId);

    // Then
    assertEquals(mockUser, result);
}

2. Интеграционные тесты

Здесь мы тестируем взаимодействие между различными компонентами приложения — например, вызов GraphQL-запроса и обработку его Resolver'ом.

Инструменты: Spring Boot Test, MockMvc.

Пример:


@Test
void testGraphQLQuery() throws Exception {
    String query = "{ user(id: \"1\") { firstName lastName } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + query + "\"}"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.data.user.firstName").value("John"))
            .andExpect(jsonPath("$.data.user.lastName").value("Doe"));
}

3. Контрактное тестирование

Используется для проверки взаимодействия между микросервисами. Например, если один микросервис предоставляет GraphQL API, а другой к нему обращается, важно убедиться, что договоренности о формате запросов и ответов соблюдаются.

Инструмент: Pact.

4. Нагрузочное тестирование

Позволяет проверить, как API справляется с большим количеством запросов одновременно.

Инструмент: k6.


Использование JUnit для тестирования GraphQL

JUnit — это стандартный фреймворк для тестирования в Java, и он отлично подходит для проверки бизнес-логики GraphQL. Давайте начнем с простого теста Resolver'а.

Пример теста Resolver'а:


@Test
void testResolveQuery() {
    // Given
    String query = "{ user(id: \"1\") { firstName, lastName } }";
    ExecutionInput executionInput = ExecutionInput.newExecutionInput()
            .query(query)
            .build();

    // When
    ExecutionResult executionResult = graphQL.execute(executionInput);

    // Then
    Map<String, Object7>) data.get("user")).get("firstName"));
}

Здесь мы создаем графQL-запрос и проверяем, что данные возвращаются корректно.


Практика: тестирование GraphQL API с использованием JUnit и MockMvc

MockMvc — это мощный инструмент для интеграционного тестирования Spring-приложений, включая GraphQL API.

1. Настройка тестов

Для начала убедитесь, что у вас настроен Spring Boot Test. Для тестирования GraphQL запросов через MockMvc необходимо настроить ваш контроллер.

Пример конфигурации:

@Autowired
private MockMvc mockMvc;

2. Написание тестового сценария

Тестируем запрос на получение пользователя:


@Test
void testUserQuery() throws Exception {
    String query = "{ user(id: \"1\") { firstName, lastName } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + query + "\"}"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.data.user.firstName").value("John"))
            .andExpect(jsonPath("$.data.user.lastName").value("Doe"));
}

Здесь мы проверяем, что запрос срабатывает и возвращает ожидаемые данные.


Тестирование сложных запросов и мутаций

В более сложных сценариях API может возвращать вложенные объекты или выполнять мутации данных.

Пример сложного запроса:


@Test
void testComplexQuery() throws Exception {
    String query = "{ user(id: \"1\") { firstName, posts { title, content } } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + query + "\"}"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.data.user.firstName").value("John"))
            .andExpect(jsonPath("$.data.user.posts[0].title").value("Post 1"))
            .andExpect(jsonPath("$.data.user.posts[0].content").value("Content 1"));
}

Пример мутации:


@Test
void testCreateUserMutation() throws Exception {
    String mutation = "mutation { createUser(input: { firstName: \"Jane\", lastName: \"Doe\" }) { id, firstName, lastName } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + mutation + "\"}"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.data.createUser.firstName").value("Jane"))
            .andExpect(jsonPath("$.data.createUser.lastName").value("Doe"));
}

Тестирование безопасности и производительности

Проверьте, что пользователи без необходимых прав доступа не могут выполнять определенные запросы.

Пример проверки прав:


@Test
@WithMockUser(roles = "ADMIN")
void testAdminAccess() throws Exception {
    String query = "{ adminData { sensitiveInfo } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + query + "\"}"))
            .andExpect(status().isOk());
}

@Test
@WithMockUser(roles = "USER")
void testUnauthorizedAccess() throws Exception {
    String query = "{ adminData { sensitiveInfo } }";

    mockMvc.perform(post("/graphql")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{\"query\":\"" + query + "\"}"))
            .andExpect(status().isForbidden());
}

Используйте инструменты, такие как k6, для проверки производительности:

k6 run --vus 10 --iterations 100 script.js

Итоги

Теперь у вас есть знания и примеры для написания тестов для GraphQL API. Вы можете проверять как логику отдельных компонентов, так и взаимодействие различных частей системы. Уделяйте особое внимание безопасности и производительности — это ключевые аспекты в реальной разработке.

Все ваши тесты помогут предотвратить баги до того, как они попадут в продакшен. А это значит: спокойный сон и благодарные пользователи!

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ