mirror of
				https://github.com/graphql-python/graphene-django.git
				synced 2025-11-04 09:57:53 +03:00 
			
		
		
		
	Extract query function from GraphQLTestCase making it possible to use in a pytest fixture (#1015)
This commit is contained in:
		
							parent
							
								
									97de26bf2e
								
							
						
					
					
						commit
						2308965658
					
				| 
						 | 
					@ -1,6 +1,9 @@
 | 
				
			||||||
Testing API calls with django
 | 
					Testing API calls with django
 | 
				
			||||||
=============================
 | 
					=============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using unittest
 | 
				
			||||||
 | 
					--------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you want to unittest your API calls derive your test case from the class `GraphQLTestCase`.
 | 
					If you want to unittest your API calls derive your test case from the class `GraphQLTestCase`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Your endpoint is set through the `GRAPHQL_URL` attribute on `GraphQLTestCase`. The default endpoint is `GRAPHQL_URL = "/graphql/"`.
 | 
					Your endpoint is set through the `GRAPHQL_URL` attribute on `GraphQLTestCase`. The default endpoint is `GRAPHQL_URL = "/graphql/"`.
 | 
				
			||||||
| 
						 | 
					@ -12,12 +15,8 @@ Usage:
 | 
				
			||||||
    import json
 | 
					    import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    from graphene_django.utils.testing import GraphQLTestCase
 | 
					    from graphene_django.utils.testing import GraphQLTestCase
 | 
				
			||||||
    from my_project.config.schema import schema
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class MyFancyTestCase(GraphQLTestCase):
 | 
					    class MyFancyTestCase(GraphQLTestCase):
 | 
				
			||||||
        # Here you need to inject your test case's schema
 | 
					 | 
				
			||||||
        GRAPHQL_SCHEMA = schema
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def test_some_query(self):
 | 
					        def test_some_query(self):
 | 
				
			||||||
            response = self.query(
 | 
					            response = self.query(
 | 
				
			||||||
                '''
 | 
					                '''
 | 
				
			||||||
| 
						 | 
					@ -82,3 +81,38 @@ Usage:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Add some more asserts if you like
 | 
					            # Add some more asserts if you like
 | 
				
			||||||
            ...
 | 
					            ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using pytest
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To use pytest define a simple fixture using the query helper below
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. code:: python
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Create a fixture using the graphql_query helper and `client` fixture from `pytest-django`.
 | 
				
			||||||
 | 
					        import pytest
 | 
				
			||||||
 | 
					        from graphene_django.utils.testing import graphql_query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @pytest.fixture
 | 
				
			||||||
 | 
					        def client_query(client)
 | 
				
			||||||
 | 
					            def func(*args, **kwargs):
 | 
				
			||||||
 | 
					                return graphql_query(*args, **kwargs, client=client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return func
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Test you query using the client_query fixture
 | 
				
			||||||
 | 
					        def test_some_query(client_query):
 | 
				
			||||||
 | 
					            response = graphql_query(
 | 
				
			||||||
 | 
					                '''
 | 
				
			||||||
 | 
					                query {
 | 
				
			||||||
 | 
					                    myModel {
 | 
				
			||||||
 | 
					                        id
 | 
				
			||||||
 | 
					                        name
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                ''',
 | 
				
			||||||
 | 
					                op_name='myModel'
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            content = json.loads(response.content)
 | 
				
			||||||
 | 
					            assert 'errors' not in content
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ from mock import patch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ..utils import camelize, get_model_fields, GraphQLTestCase
 | 
					from ..utils import camelize, get_model_fields, GraphQLTestCase
 | 
				
			||||||
from .models import Film, Reporter
 | 
					from .models import Film, Reporter
 | 
				
			||||||
 | 
					from ..utils.testing import graphql_query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_get_model_fields_no_duplication():
 | 
					def test_get_model_fields_no_duplication():
 | 
				
			||||||
| 
						 | 
					@ -58,3 +59,29 @@ def test_graphql_test_case_op_name(post_mock):
 | 
				
			||||||
        "operationName",
 | 
					        "operationName",
 | 
				
			||||||
        "QueryName",
 | 
					        "QueryName",
 | 
				
			||||||
    ) in body.items(), "Field 'operationName' is not present in the final request."
 | 
					    ) in body.items(), "Field 'operationName' is not present in the final request."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.mark.django_db
 | 
				
			||||||
 | 
					@patch("graphene_django.utils.testing.Client.post")
 | 
				
			||||||
 | 
					def test_graphql_query_case_op_name(post_mock):
 | 
				
			||||||
 | 
					    graphql_query("query { }", op_name="QueryName")
 | 
				
			||||||
 | 
					    body = json.loads(post_mock.call_args.args[1])
 | 
				
			||||||
 | 
					    # `operationName` field from https://graphql.org/learn/serving-over-http/#post-request
 | 
				
			||||||
 | 
					    assert (
 | 
				
			||||||
 | 
					        "operationName",
 | 
				
			||||||
 | 
					        "QueryName",
 | 
				
			||||||
 | 
					    ) in body.items(), "Field 'operationName' is not present in the final request."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@pytest.fixture
 | 
				
			||||||
 | 
					def client_query(client):
 | 
				
			||||||
 | 
					    def func(*args, **kwargs):
 | 
				
			||||||
 | 
					        return graphql_query(*args, client=client, **kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return func
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_pytest_fixture_usage(client_query):
 | 
				
			||||||
 | 
					    response = graphql_query("query { test }")
 | 
				
			||||||
 | 
					    content = json.loads(response.content)
 | 
				
			||||||
 | 
					    assert content == {"data": {"test": "Hello World"}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,63 @@ import json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.test import TestCase, Client
 | 
					from django.test import TestCase, Client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEFAULT_GRAPHQL_URL = "/graphql/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def graphql_query(
 | 
				
			||||||
 | 
					    query,
 | 
				
			||||||
 | 
					    op_name=None,
 | 
				
			||||||
 | 
					    input_data=None,
 | 
				
			||||||
 | 
					    variables=None,
 | 
				
			||||||
 | 
					    headers=None,
 | 
				
			||||||
 | 
					    client=None,
 | 
				
			||||||
 | 
					    graphql_url=None,
 | 
				
			||||||
 | 
					):
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    Args:
 | 
				
			||||||
 | 
					        query (string)              - GraphQL query to run
 | 
				
			||||||
 | 
					        op_name (string)            - If the query is a mutation or named query, you must
 | 
				
			||||||
 | 
					                                      supply the op_name.  For annon queries ("{ ... }"),
 | 
				
			||||||
 | 
					                                      should be None (default).
 | 
				
			||||||
 | 
					        input_data (dict)           - If provided, the $input variable in GraphQL will be set
 | 
				
			||||||
 | 
					                                      to this value. If both ``input_data`` and ``variables``,
 | 
				
			||||||
 | 
					                                      are provided, the ``input`` field in the ``variables``
 | 
				
			||||||
 | 
					                                      dict will be overwritten with this value.
 | 
				
			||||||
 | 
					        variables (dict)            - If provided, the "variables" field in GraphQL will be
 | 
				
			||||||
 | 
					                                      set to this value.
 | 
				
			||||||
 | 
					        headers (dict)              - If provided, the headers in POST request to GRAPHQL_URL
 | 
				
			||||||
 | 
					                                      will be set to this value.
 | 
				
			||||||
 | 
					        client (django.test.Client) - Test client. Defaults to django.test.Client.
 | 
				
			||||||
 | 
					        graphql_url (string)        - URL to graphql endpoint. Defaults to "/graphql".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Returns:
 | 
				
			||||||
 | 
					        Response object from client
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    if client is None:
 | 
				
			||||||
 | 
					        client = Client()
 | 
				
			||||||
 | 
					    if not graphql_url:
 | 
				
			||||||
 | 
					        graphql_url = DEFAULT_GRAPHQL_URL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    body = {"query": query}
 | 
				
			||||||
 | 
					    if op_name:
 | 
				
			||||||
 | 
					        body["operationName"] = op_name
 | 
				
			||||||
 | 
					    if variables:
 | 
				
			||||||
 | 
					        body["variables"] = variables
 | 
				
			||||||
 | 
					    if input_data:
 | 
				
			||||||
 | 
					        if variables in body:
 | 
				
			||||||
 | 
					            body["variables"]["input"] = input_data
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            body["variables"] = {"input": input_data}
 | 
				
			||||||
 | 
					    if headers:
 | 
				
			||||||
 | 
					        resp = client.post(
 | 
				
			||||||
 | 
					            graphql_url, json.dumps(body), content_type="application/json", **headers
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        resp = client.post(
 | 
				
			||||||
 | 
					            graphql_url, json.dumps(body), content_type="application/json"
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    return resp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GraphQLTestCase(TestCase):
 | 
					class GraphQLTestCase(TestCase):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
| 
						 | 
					@ -9,19 +66,12 @@ class GraphQLTestCase(TestCase):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # URL to graphql endpoint
 | 
					    # URL to graphql endpoint
 | 
				
			||||||
    GRAPHQL_URL = "/graphql/"
 | 
					    GRAPHQL_URL = DEFAULT_GRAPHQL_URL
 | 
				
			||||||
    # Here you need to set your graphql schema for the tests
 | 
					 | 
				
			||||||
    GRAPHQL_SCHEMA = None
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def setUpClass(cls):
 | 
					    def setUpClass(cls):
 | 
				
			||||||
        super(GraphQLTestCase, cls).setUpClass()
 | 
					        super(GraphQLTestCase, cls).setUpClass()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not cls.GRAPHQL_SCHEMA:
 | 
					 | 
				
			||||||
            raise AttributeError(
 | 
					 | 
				
			||||||
                "Variable GRAPHQL_SCHEMA not defined in GraphQLTestCase."
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cls._client = Client()
 | 
					        cls._client = Client()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def query(self, query, op_name=None, input_data=None, variables=None, headers=None):
 | 
					    def query(self, query, op_name=None, input_data=None, variables=None, headers=None):
 | 
				
			||||||
| 
						 | 
					@ -43,28 +93,15 @@ class GraphQLTestCase(TestCase):
 | 
				
			||||||
        Returns:
 | 
					        Returns:
 | 
				
			||||||
            Response object from client
 | 
					            Response object from client
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        body = {"query": query}
 | 
					        return graphql_query(
 | 
				
			||||||
        if op_name:
 | 
					            query,
 | 
				
			||||||
            body["operationName"] = op_name
 | 
					            op_name=op_name,
 | 
				
			||||||
        if variables:
 | 
					            input_data=input_data,
 | 
				
			||||||
            body["variables"] = variables
 | 
					            variables=variables,
 | 
				
			||||||
        if input_data:
 | 
					            headers=headers,
 | 
				
			||||||
            if variables in body:
 | 
					            client=self._client,
 | 
				
			||||||
                body["variables"]["input"] = input_data
 | 
					            graphql_url=self.GRAPHQL_URL,
 | 
				
			||||||
            else:
 | 
					        )
 | 
				
			||||||
                body["variables"] = {"input": input_data}
 | 
					 | 
				
			||||||
        if headers:
 | 
					 | 
				
			||||||
            resp = self._client.post(
 | 
					 | 
				
			||||||
                self.GRAPHQL_URL,
 | 
					 | 
				
			||||||
                json.dumps(body),
 | 
					 | 
				
			||||||
                content_type="application/json",
 | 
					 | 
				
			||||||
                **headers
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            resp = self._client.post(
 | 
					 | 
				
			||||||
                self.GRAPHQL_URL, json.dumps(body), content_type="application/json"
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        return resp
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assertResponseNoErrors(self, resp):
 | 
					    def assertResponseNoErrors(self, resp):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user