Тестування GraphQL API — важливий етап розробки, воно забезпечує коректність роботи схеми, запитів, мутацій та безпеку даних. Ми будемо використовувати JUnit і MockMvc — інструменти, які вже давно зарекомендували себе при тестуванні Spring додатків. Унікальність тестування GraphQL API в тому, що потрібно перевіряти запити подібно до REST, але з урахуванням особливостей GraphQL, таких як вибір тільки запитаних полів і складні вкладені структури.
Налаштування тестового оточення для GraphQL
Перед початком тестування потрібно правильно налаштувати тестове середовище. Ми додамо всі потрібні залежності, налаштуємо тестові дані і підготуємо MockMvc для роботи з GraphQL-запитами.
Додаємо залежності в pom.xml
Переконайтеся, що у вас підключені наступні залежності:
<dependencies>
<!-- Залежності для GraphQL -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>15.0.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>11.1.0</version>
</dependency>
<!-- Залежності для тестування -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.graphql</groupId>
<artifactId>spring-graphql-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2. Налаштування тестового контексту
Використовуємо анотацію @SpringBootTest, щоб підняти контекст додатка під час тестів. Крім того, підключимо MockMvc для відправки запитів.
@SpringBootTest
@AutoConfigureMockMvc
public class GraphQLTest {
@Autowired
private MockMvc mockMvc;
}
Написання тестових сценаріїв
Давайте напишемо кілька тестів для перевірки нашого GraphQL API. Ми будемо тестувати запити, мутації та обробку помилок.
1. Тестування GraphQL запиту
Припустимо, у нас є схема schema.graphql:
type Query {
getBook(id: ID!): Book
}
type Book {
id: ID!
title: String
author: String
}
Ми тестуємо запит, щоб отримати книгу за ID:
query {
getBook(id: "1") {
id
title
author
}
}
Тестовий метод для цього запиту:
@Test
void testGetBookQuery() throws Exception {
String query = """
{
"query": "query { getBook(id: \\"1\\") { id title author } }"
}
""";
mockMvc.perform(post("/graphql")
.contentType(MediaType.APPLICATION_JSON)
.content(query))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.getBook.id").value("1"))
.andExpect(jsonPath("$.data.getBook.title").value("GraphQL for Beginners"))
.andExpect(jsonPath("$.data.getBook.author").value("John Doe"));
}
У коді:
- У
queryми формуємо тіло GraphQL-запиту у форматі JSON. - Використовуємо MockMvc для відправки POST-запиту на
/graphql. - Перевіряємо статус відповіді за допомогою
status().isOk(). - Перевіряємо дані відповіді через
jsonPath.
2. Тестування мутації
Якщо в нас є мутація для додавання нової книги:
mutation {
addBook(input: { title: "Spring Boot with GraphQL", author: "Jane Doe" }) {
id
title
author
}
}
Тестовий метод для мутації:
@Test
void testAddBookMutation() throws Exception {
String mutation = """
{
"query": "mutation { addBook(input: { title: \\"Spring Boot with GraphQL\\", author: \\"Jane Doe\\" }) { id title author } }"
}
""";
mockMvc.perform(post("/graphql")
.contentType(MediaType.APPLICATION_JSON)
.content(mutation))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.addBook.title").value("Spring Boot with GraphQL"))
.andExpect(jsonPath("$.data.addBook.author").value("Jane Doe"));
}
Зверніть увагу, що ми перевіряємо поля, які повертає мутація. Це допомагає переконатися, що мутація працює коректно.
3. Тестування помилок
GraphQL API часто повертає помилки в полі errors. Давайте протестуємо, що станеться, якщо запитувана книга не знайдена:
query {
getBook(id: "999") {
id
title
author
}
}
Тестовий метод:
@Test
void testGetBookNotFound() throws Exception {
String query = """
{
"query": "query { getBook(id: \\"999\\") { id title author } }"
}
""";
mockMvc.perform(post("/graphql")
.contentType(MediaType.APPLICATION_JSON)
.content(query))
.andExpect(status().isOk())
.andExpect(jsonPath("$.errors").exists())
.andExpect(jsonPath("$.errors[0].message").value("Book not found"));
}
Тут ми перевіряємо, що поле errors присутнє, і помилка містить повідомлення "Book not found".
Тестування складних запитів
Складні GraphQL-запити можуть включати вкладені поля і кілька рівнів даних. Наприклад:
query {
getBook(id: "1") {
id
title
author
reviews {
reviewer
comment
}
}
}
Тестуємо цей запит аналогічно — перевіряємо вкладені структури JSON:
@Test
void testGetBookWithReviews() throws Exception {
String query = """
{
"query": "query { getBook(id: \\"1\\") { id title author reviews { reviewer comment } } }"
}
""";
mockMvc.perform(post("/graphql")
.contentType(MediaType.APPLICATION_JSON)
.content(query))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.getBook.reviews[0].reviewer").value("Alice"))
.andExpect(jsonPath("$.data.getBook.reviews[0].comment").value("Great book!"));
}
Тестування безпеки
Якщо в нас є аутентифікація через токен (наприклад, JWT), можемо додати токен у заголовок:
@Test
void testAuthorizedQuery() throws Exception {
String query = """
{
"query": "query { getBook(id: \\"1\\") { id title author } }"
}
""";
mockMvc.perform(post("/graphql")
.header(HttpHeaders.AUTHORIZATION, "Bearer mock-jwt-token")
.contentType(MediaType.APPLICATION_JSON)
.content(query))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.getBook.title").value("GraphQL for Beginners"));
}
Підсумок
Тестування GraphQL API з використанням JUnit і MockMvc — це потужний спосіб забезпечити стабільність і коректність вашого додатка. Ми розглянули тестування запитів, мутацій, помилок, складних вкладених структур і безпеки. Ці підходи допоможуть вам впевнено готувати додаток до продакшену.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ