Skip to content

Commit b491878

Browse files
author
Ronny Vedrilla
committed
* Added test class for django api unittests and documentation how to use it
1 parent ea2cd98 commit b491878

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Contents:
1414
rest-framework
1515
form-mutations
1616
introspection
17+
testing

docs/testing.rst

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
Testing API calls with django
2+
=============================
3+
4+
If you want to unittest your API calls derive your test case from the class `GraphQLTestCase`.
5+
6+
Usage:
7+
8+
.. code:: python
9+
10+
import json
11+
12+
from graphene_django.tests.base_test import GraphQLTestCase
13+
from my_project.config.schema import schema
14+
15+
class MyFancyTestCase(GraphQLTestCase):
16+
# Here you need to inject your test case's schema
17+
GRAPHQL_SCHEMA = schema
18+
19+
def test_some_query(self):
20+
response = self.query(
21+
'''
22+
query {
23+
myModel {
24+
id
25+
name
26+
}
27+
}
28+
''',
29+
op_name='myModel'
30+
)
31+
32+
content = json.loads(response.content)
33+
34+
# This validates the status code and if you get errors
35+
self.assertResponseNoErrors(response)
36+
37+
# Add some more asserts if you like
38+
...
39+
40+
def test_some_mutation(self):
41+
response = self.query(
42+
'''
43+
mutation myMutation($input: MyMutationInput!) {
44+
myMutation(input: $input) {
45+
my-model {
46+
id
47+
name
48+
}
49+
}
50+
}
51+
''',
52+
op_name='myMutation',
53+
input_data={'my_field': 'foo', 'other_field': 'bar'}
54+
)
55+
56+
# This validates the status code and if you get errors
57+
self.assertResponseNoErrors(response)
58+
59+
# Add some more asserts if you like
60+
...

graphene_django/tests/base_test.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import json
2+
3+
from django.http import HttpResponse
4+
from django.test import Client
5+
from django.test import TestCase
6+
7+
8+
class GraphQLTestCase(TestCase):
9+
"""
10+
Based on: https://www.sam.today/blog/testing-graphql-with-graphene-django/
11+
"""
12+
13+
# URL to graphql endpoint
14+
GRAPHQL_URL = '/graphql/'
15+
# Here you need to set your graphql schema for the tests
16+
GRAPHQL_SCHEMA = None
17+
18+
@classmethod
19+
def setUpClass(cls):
20+
super().setUpClass()
21+
22+
if not cls.GRAPHQL_SCHEMA:
23+
raise AttributeError('Variable GRAPHQL_SCHEMA not defined in GraphQLTestCase.')
24+
25+
cls._client = Client(cls.GRAPHQL_SCHEMA)
26+
27+
def query(self, query: str, op_name: str = None, input_data: dict = None):
28+
"""
29+
Args:
30+
query (string) - GraphQL query to run
31+
op_name (string) - If the query is a mutation or named query, you must
32+
supply the op_name. For annon queries ("{ ... }"),
33+
should be None (default).
34+
input_data (dict) - If provided, the $input variable in GraphQL will be set
35+
to this value
36+
37+
Returns:
38+
Response object from client
39+
"""
40+
body = {'query': query}
41+
if op_name:
42+
body['operation_name'] = op_name
43+
if input_data:
44+
body['variables'] = {'input': input_data}
45+
46+
resp = self._client.post(self.GRAPHQL_URL, json.dumps(body),
47+
content_type='application/json')
48+
return resp
49+
50+
def assertResponseNoErrors(self, resp: HttpResponse):
51+
"""
52+
Assert that the call went through correctly. 200 means the syntax is ok, if there are no `errors`,
53+
the call was fine.
54+
"""
55+
content = json.loads(resp.content)
56+
self.assertEqual(resp.status_code, 200)
57+
self.assertNotIn('errors', list(content.keys()))
58+
59+
def assertResponseHasErrors(self, resp: HttpResponse):
60+
"""
61+
Assert that the call was failing. Take care: Even with errors, GraphQL returns status 200!
62+
"""
63+
content = json.loads(resp.content)
64+
self.assertIn('errors', list(content.keys()))

0 commit comments

Comments
 (0)