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

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

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

Тестирование 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 — это мощный способ обеспечить стабильность и корректность вашего приложения. Мы рассмотрели тестирование запросов, мутаций, ошибок, сложных вложенных структур и безопасности. Эти подходы помогут вам уверенно готовить приложение к продакшену.

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