Probar GraphQL API es una etapa importante del desarrollo; garantiza la corrección de los esquemas, las consultas, las mutations y la seguridad de los datos. Vamos a usar JUnit y MockMvc — herramientas que llevan tiempo demostrando su valía en las pruebas de aplicaciones Spring. La particularidad de testear GraphQL API es la necesidad de verificar las consultas de forma parecida a REST, pero teniendo en cuenta las características propias de GraphQL, como seleccionar solo los campos solicitados y gestionar estructuras anidadas complejas.
Configuración del entorno de pruebas para GraphQL
Antes de comenzar con las pruebas hay que configurar correctamente el entorno de testing. Añadiremos las dependencias necesarias, prepararemos los datos de prueba y configuraremos MockMvc para trabajar con peticiones GraphQL.
Añadimos dependencias en pom.xml
Asegúrate de tener las siguientes dependencias:
<dependencies>
<!-- Dependencias para 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>
<!-- Dependencias para pruebas -->
<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. Configuración del contexto de pruebas
Usamos la anotación @SpringBootTest para levantar el contexto de la aplicación durante las pruebas. Además, configuramos MockMvc para enviar las peticiones.
@SpringBootTest
@AutoConfigureMockMvc
public class GraphQLTest {
@Autowired
private MockMvc mockMvc;
}
Escribir escenarios de prueba
Vamos a escribir algunos tests para comprobar nuestro GraphQL API. Probaremos queries, mutations y el manejo de errores.
1. Test de una consulta GraphQL
Supongamos que tenemos el esquema schema.graphql:
type Query {
getBook(id: ID!): Book
}
type Book {
id: ID!
title: String
author: String
}
Probamos la consulta para obtener un libro por ID:
query {
getBook(id: "1") {
id
title
author
}
}
Método de prueba para esa consulta:
@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"));
}
En el código:
- En
queryformamos el cuerpo de la petición GraphQL en formato JSON. - Usamos MockMvc para enviar un POST a
/graphql. - Comprobamos el estado de la respuesta con
status().isOk(). - Verificamos los datos de la respuesta con
jsonPath.
2. Testeo de mutation
Si tenemos una mutation para añadir un nuevo libro:
mutation {
addBook(input: { title: "Spring Boot with GraphQL", author: "Jane Doe" }) {
id
title
author
}
}
Método de prueba para la 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"));
}
Fíjate que comprobamos los campos que devuelve la mutation. Esto ayuda a asegurar que la mutation funciona correctamente.
3. Testeo de errores
Las GraphQL APIs suelen devolver errores en el campo errors. Probemos qué pasa si el libro solicitado no se encuentra:
query {
getBook(id: "999") {
id
title
author
}
}
Método de prueba:
@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"));
}
Aquí comprobamos que el campo errors existe y que el error contiene el mensaje "Book not found".
Testeo de consultas complejas
Las consultas GraphQL complejas pueden incluir campos anidados y varios niveles de datos. Por ejemplo:
query {
getBook(id: "1") {
id
title
author
reviews {
reviewer
comment
}
}
}
Probamos esa consulta de forma similar — verificando las estructuras JSON anidadas:
@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!"));
}
Testeo de seguridad
Si usamos autenticación por token (por ejemplo, JWT), podemos añadir el token en el 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"));
}
Resumen
Testear GraphQL API con JUnit y MockMvc es una forma potente de asegurar la estabilidad y la corrección de tu aplicación. Hemos visto cómo testear queries, mutations, errores, estructuras anidadas complejas y seguridad. Estos enfoques te ayudarán a preparar tu aplicación con confianza para producción.
GO TO FULL VERSION