Кожен розробник знає, що чим менше багів в 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. Ти можеш перевіряти як логіку окремих компонентів, так і взаємодію різних частин системи. Увага до безпеки й продуктивності — це ключові аспекти в реальній розробці.
Усі твої тести допоможуть запобігти багам до того, як вони потраплять у продакшн. А це означає: спокійний сон і вдячні користувачі!
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ