Implement graphql server API with springboot and automate test using requests in Python
cuongld2
Posted on January 4, 2020
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
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, 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
<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:
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.
@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:
@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:
@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
Or you might want to run a graphiql app like in here which I'm currently using.
1.Add header content:
2.Get a number of blogs with only id and content info:
3.Get a blog post by its id:
III.Automate tests with requests in Python
1.Define method get blogs info by query and its token
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:
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
automate-test-python
Happy coding!
Notes: If you feel this blog help you and want to show the appreciation, feel free to drop by :
This will help me to contributing more valued contents.
Posted on January 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
January 4, 2020