Implement graphql server API with springboot and automate test using requests in Python
Tags: springboot, graphql, requests, automation
Published: 2020-01-04 13:47:33

---
title: Implement graphql server API with springboot and automate test using requests in Python
published: true
description: 
tags: #springboot #graphql #requests #automation
---

GraphQL is getting more and more attention from development community as it allows us to get only the data we need.

You can find out more about graphql in [here](https://graphql.org/)

In this post I will walk through how to create a simple graphql API server in spring-boot and how to do automated testing it with requests in Python.

You might want to check [my previous post](https://dev.to/cuongld2/create-apis-with-jwt-authorization-using-spring-boot-24f9), which I already mentioned how to create a blog app in springboot as in this post, I will continue using that and implemented a graphql server based on that.

I.GraphQL server:
  Basically, I will keep all the other APIs from the old posts. I just write some new queries support to get the blog post data.

  1.Dependencies:
You will need the below dependencies for implemented graphql in java and graphiql for usage

```javascript
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphql-java-tools</artifactId>
            <version>5.2.4</version>
        </dependency>
        <dependency>
            <groupId>com.graphql-java</groupId>
            <artifactId>graphiql-spring-boot-starter</artifactId>
            <version>5.0.2</version>
        </dependency>
```
  2.GraphQL Schema:
We need to define the schema for what kind of queries and what kind of objects will be supported.
Below is how we defined the schema:

```javascript
type Blog {
    id: Int,
    title: String,
    content: String
}

type Query {
    blogs(count: Int):[Blog]
    blog(id: Int):Blog
}
```
We will support 2 kinds of queries.
1.Get a number of blogs based on the count parameter
2.Get a blog content by its id

  3.Blog service:
Define the methods to return the blogs info.

```javascript

@Service
public class BlogService {

    private final BlogRepository blogRepository;

    public BlogService(final BlogRepository blogRepository){this.blogRepository = blogRepository;}

    @Transactional(readOnly = true)
    public List<Blog> getAllBlogs(final int count){
        return this.blogRepository.findAll().stream().limit(count).collect(Collectors.toList());
    }

    @Transactional(readOnly = true)
    public Optional<Blog> getBlog(final int id){return this.blogRepository.findById(id);}
}

```

  4.Blog query:
Define the methods to return the blog service info:

```javascript

@Component
public class BlogQuery implements GraphQLQueryResolver {

    @Autowired
    private BlogService blogService;

    public List<Blog> getBlogs(final int count){
        return this.blogService.getAllBlogs(count);
    }


    public Optional<Blog> getBlog(final int id){return this.blogService.getBlog(id);}

}

```

  5.Security:
As in the previous post, we already defined this:

```javascript
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity.csrf().disable()

                .authorizeRequests().antMatchers("/authenticate","/user").permitAll().

        anyRequest().authenticated().and().

        exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()

                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

    }

```
that means if the endpoint is not start with /authenticate or /user, they will need the header token.

So in order for later to get blogs information by graphql server, we will need to provide the necessary token.

  6.Run the graphql server:
As usual run with 

mvn spring-boot:run

II.GraphiQL:

GrahpiQL is a way to interact with graphql server.
You can access to the grahqpl server by opening this in browser (exp: Chrome) :

http://localhost:8082/graphql
But remember as I mention earlier, it needs the token to access, so you might want to install another extension into your chrome browser like :
[mod header](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj)

Or you might want to run a graphiql app like [in here](https://electronjs.org/apps/graphiql) which I'm currently using.

1.Add header content:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fp73hmlzqh1tiens268a.png)

2.Get a number of blogs with only id and content info:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/cezpy5h4f089cgdm34kz.png)

3.Get a blog post by its id:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fvm24tcq2471h5z7xqe7.png)

III.Automate tests with requests in Python

1.Define method get blogs info by query and its token


```javascript
class Blogs:

    def get_blog_info(self, query, token):
        request = requests.post(API_SERVER_URL + API_GRAPH_QL_PATH, json={'query': query}, headers={"Authorization": f"Bearer {token}"})
        if request.status_code == 200:
            return request.json()
        else:
            raise Exception("Query failed to run by returning code of {}. {}".format(request.status_code, query))

```
2.Write test script to create new user, get token and use that token to query the information we need:

```javascript

class TestGetBlogsInfo:
    user_api = User()
    restapi_query = RestAPIDatabase()
    random_gen = RandomGenerator()
    blog_graphql_api = Blogs()

    @pytestrail.case('C8')
    def test_get_all_blog_id_and_contents_with_count(self, set_up_mysql):
        username = self.random_gen.random_string(8) + '@gmail.com'
        query = """
        {
            blogs(count:1){
                            id,
                            content
                            }
        }
        """
        try:
            response = self.user_api.create_new_user_data_class(username, 'Abcd12345$', 'Le Dinh Cuong')
            assert 200 == response.status_code
            response = self.user_api.authen_user_login(username, 'Abcd12345$')
            assert response.status_code == 200
            token_object = json.loads(response.text)
            assert token_object['token'] is not None
            response_blog = self.blog_graphql_api.get_blog_info(query, token_object['token'])
            print(response_blog)
            assert response_blog['data']['blogs'][0]['id'] == 1
            if 'title' in response_blog['data']['blogs'][0]:
                raise print('Content existed in response')
            assert 'title' not in str(response_blog)
        finally:
            self.restapi_query.delete_user_info_by_username(set_up_mysql, username)

```

I know it's pretty tough and there might be something you might don't understand, but feel free to ask me in the comment.

Below is the link for source code for implemented the graphql server app and the test repo.

[spring-boot-graphql](https://github.com/cuongld2/springboot-simpleAPI)
[automate-test-python](https://github.com/cuongld2/automationTestPython)

Happy coding!

Notes: If you feel this blog help you and want to show the appreciation, feel free to drop by :

[<img src="https://thepracticaldev.s3.amazonaws.com/i/cno42wb8aik6o9ek1f89.png">](https://www.buymeacoffee.com/dOaeSPv
)

This will help me to contributing more valued contents.