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

Лекція 297: Тестування GraphQL API

Модуль 5. Spring
Рівень 16 , Лекція 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"));
}

Тут ми створюємо GraphQL-запит і перевіряємо, що дані повертаються коректно.


Практика: тестування 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. Ти можеш перевіряти як логіку окремих компонентів, так і взаємодію різних частин системи. Увага до безпеки й продуктивності — це ключові аспекти в реальній розробці.

Усі твої тести допоможуть запобігти багам до того, як вони потраплять у продакшн. А це означає: спокійний сон і вдячні користувачі!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ