CodeGym /Courses /Module 5. Spring /Lecture 298: Practice: Testing GraphQL API with JUnit and...

Lecture 298: Practice: Testing GraphQL API with JUnit and MockMvc

Module 5. Spring
Level 16 , Lesson 7
Available

Testing a GraphQL API is an important part of development — it ensures the schema, queries, mutations, and data safety work correctly. We'll use JUnit and MockMvc — tools that have proven themselves over time for testing Spring applications. The uniqueness of testing GraphQL APIs comes from the need to validate queries similarly to REST, while accounting for GraphQL specifics like selecting only requested fields and handling complex nested structures.


Setting up the test environment for GraphQL

Before starting tests you need to set up the test environment properly. We'll add the required dependencies, configure test data, and prepare MockMvc to work with GraphQL requests.

Add dependencies to pom.xml

Make sure you have the following dependencies included:


<dependencies>
    <!-- Dependencies for 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>

    <!-- Testing dependencies -->
    <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. Test context setup

We use the @SpringBootTest annotation to bring up the application context during tests. Also wire MockMvc to send requests.


@SpringBootTest
@AutoConfigureMockMvc
public class GraphQLTest {
    @Autowired
    private MockMvc mockMvc;
}

Writing test scenarios

Let's write a few tests for our GraphQL API. We'll test queries, mutations, and error handling.

1. Testing a GraphQL query

Suppose we have a schema schema.graphql:


type Query {
    getBook(id: ID!): Book
}

type Book {
    id: ID!
    title: String
    author: String
}

We'll test a query to fetch a book by ID:


query {
    getBook(id: "1") {
        id
        title
        author
    }
}

Test method for this query:


@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"));
}

In the code:

  • In query we build the GraphQL request body in JSON format.
  • We use MockMvc to send a POST to /graphql.
  • We check the response status with status().isOk().
  • We validate the response data using jsonPath.

2. Testing a mutation

If we have a mutation to add a new book:


mutation {
    addBook(input: { title: "Spring Boot with GraphQL", author: "Jane Doe" }) {
        id
        title
        author
    }
}

Test method for the mutation:


@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"));
}

Note that we check the fields the mutation returns. This helps make sure the mutation works correctly.


3. Testing errors

GraphQL APIs often return errors in the errors field. Let's test what happens if the requested book isn't found:


query {
    getBook(id: "999") {
        id
        title
        author
    }
}

Test method:


@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"));
}

Here we check that the errors field is present and that the error contains the message "Book not found".


Testing complex queries

Complex GraphQL queries can include nested fields and multiple levels of data. For example:

query {
    getBook(id: "1") {
        id
        title
        author
        reviews {
            reviewer
            comment
        }
    }
}

Test this query similarly — validate the nested JSON structures:


@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!"));
}

Testing security

If we have token-based authentication (e.g., JWT), we can add the token to the header:


@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"));
}

Summary

Testing GraphQL APIs with JUnit and MockMvc is a powerful way to ensure your application's stability and correctness. We covered testing queries, mutations, errors, complex nested structures, and security. These approaches will help you confidently get your app ready for production.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION