Testing GraphQL APIs

Introduction to Testing GraphQL APIs

Welcome to the final lesson of our course! Here, we'll learn how to test GraphQL APIs, ensuring that your server is robust and reliable. Testing is crucial for maintaining the stability and functionality of your API as it evolves.

Defining the GraphQL Schema

Let's define a simple schema involving books. In Ruby with graphql-ruby, we define types as classes that inherit from GraphQL::Schema::Object. This schema includes the Book type, a Query for retrieving books, and a Mutation for adding a book.

First, let's define the Book type:

Ruby
class BookType < GraphQL::Schema::Object
  field :id, ID, null: false
  field :title, String, null: false
  field :author, String, null: false
end

Next, we'll define our Query type:

Ruby
class QueryType < GraphQL::Schema::Object
  field :books, [BookType], null: false

  def books
    # We'll implement this resolver in the next section
  end
end

And our Mutation type:

Ruby
class MutationType < GraphQL::Schema::Object
  field :add_book, BookType, null: true do
    argument :title, String, required: true
    argument :author, String, required: true
  end

  def add_book(title:, author:)
    # We'll implement this resolver in a later section
  end
end

Finally, we create the schema that ties everything together:

Ruby
class AppSchema < GraphQL::Schema
  query QueryType
  mutation MutationType
end

Here's a brief explanation:

  • BookType: Represents a book with id, title, and author fields.
  • QueryType: Contains the books field, which fetches a list of books.
  • MutationType: Contains the add_book field, which adds a new book.

Implementing and Testing Queries

Let's implement the books query and see how to test it. We'll use a simple array to store our books.

First, create a data store for our books:

Ruby
BOOKS = [
  { id: '1', title: 'The Hobbit', author: 'J.R.R. Tolkien' },
  { id: '2', title: 'Harry Potter', author: 'J.K. Rowling' }
]

Now, let's implement the resolver in our QueryType:

Ruby
class QueryType < GraphQL::Schema::Object
  field :books, [BookType], null: false

  def books
    BOOKS
  end
end

To test our query, we can use graphql-ruby's built-in execution methods. Here's a complete example:

Ruby
require 'graphql'
require 'json'

# Execute the query
query_string = <<~GRAPHQL
  query {
    books {
      id
      title
      author
    }
  }
GRAPHQL

result = AppSchema.execute(query_string)
puts JSON.pretty_generate(result.to_h)

When you run this code, you should see the following output:

JSON
{
  "data": {
    "books": [
      {
        "id": "1",
        "title": "The Hobbit",
        "author": "J.R.R. Tolkien"
      },
      {
        "id": "2",
        "title": "Harry Potter",
        "author": "J.K. Rowling"
      }
    ]
  }
}

Alternatively, if you have a Sinatra server running, you can test using HTTP requests with Net::HTTP:

Ruby
require 'net/http'
require 'json'

uri = URI('http://localhost:4000/graphql')
request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
request.body = {
  query: <<~GRAPHQL
    query {
      books {
        id
        title
        author
      }
    }
  GRAPHQL
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(request)
end

puts JSON.pretty_generate(JSON.parse(response.body))

This example demonstrates how to implement and test a simple query, ensuring your resolver functions as expected.

Implementing and Testing Mutations

Next, let's implement the addBook mutation and learn how to test it.

First, we define the resolver for the add_book mutation in our MutationType:

Ruby
class MutationType < GraphQL::Schema::Object
  field :add_book, BookType, null: true do
    argument :title, String, required: true
    argument :author, String, required: true
  end

  def add_book(title:, author:)
    new_book = {
      id: (BOOKS.length + 1).to_s,
      title: title,
      author: author
    }
    BOOKS << new_book
    new_book
  end
end

To test this mutation, we can use graphql-ruby's execution methods directly:

Ruby
require 'graphql'
require 'json'

# Execute the mutation
mutation_string = <<~GRAPHQL
  mutation {
    addBook(title: "1984", author: "George Orwell") {
      id
      title
      author
    }
  }
GRAPHQL

result = AppSchema.execute(mutation_string)
puts JSON.pretty_generate(result.to_h)

When you run this code, you should see the following output:

JSON
{
  "data": {
    "addBook": {
      "id": "3",
      "title": "1984",
      "author": "George Orwell"
    }
  }
}

You can also test the mutation using HTTP requests with Net::HTTP if you have a Sinatra server running:

Ruby
require 'net/http'
require 'json'

uri = URI('http://localhost:4000/graphql')
request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
request.body = {
  query: <<~GRAPHQL
    mutation {
      addBook(title: "1984", author: "George Orwell") {
        id
        title
        author
      }
    }
  GRAPHQL
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(request)
end

puts JSON.pretty_generate(JSON.parse(response.body))

This section demonstrates how to test a mutation by executing it directly through the schema or by sending HTTP requests to your GraphQL API endpoint, ensuring it performs correctly.

Lesson Summary

To sum up, in this lesson, you learned how to:

  • Set up a basic GraphQL environment with Ruby.
  • Define a GraphQL schema using graphql-ruby's class-based type definitions.
  • Implement and test queries and mutations using graphql-ruby and Sinatra.

These testing techniques are essential for ensuring that your GraphQL API remains robust as it scales.

You've now completed Lesson 5 and have a strong foundation in both creating and testing GraphQL APIs with Ruby. Make sure to apply these skills in your future projects and dive deeper into more advanced topics as you grow your expertise. Happy coding!

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal