【问题标题】:How to mock info.context in Django / Graphene tests如何在 Django / Graphene 测试中模拟 info.context
【发布时间】:2021-01-20 14:28:26
【问题描述】:

问题

我正在尝试测试一个 graphql 查询。该查询要求与请求关联的用户 (info.context.user) 是超级用户 (.is_superuser)。否则会抛出异常。我正在尝试测试查询是否正常工作,但不确定如何确保 info.context.user.is_superuser 在测试中解析为 true。请帮忙!

schema.py

class Query(graphene.ObjectType):
    gardens = graphene.List(GardenType)
    
    def resolve_gardens(self, info):
        user = info.context.user
        if not (user.is_superuser or user.is_staff):
            raise Exception("You must be staff or a superuser to view all gardens")
        return Garden.objects.all()

tests.py

from graphene_django.utils.testing import GraphQLTestCase, graphql_query
from users.models import CustomUser

class TestGraphQLQueries(GraphQLTestCase):
    """
    Test that GraphQL queries related to gardens work and throw errors appropriately
    """

    def test_gardens_query(self):
        response = self.query(
            """
            query {
                gardens {
                    id
                    name
                    owner {
                        id
                        email
                    }
                }
            }
            """
        )

        self.assertResponseNoErrors(response)

抛出错误


gardens/tests.py:93: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../env/lib/python3.6/site-packages/graphene_django/utils/testing.py:114: in assertResponseNoErrors
    self.assertNotIn("errors", list(content.keys()))
E   AssertionError: 'errors' unexpectedly found in ['errors', 'data']
-------------------------- Captured log call ---------------------------
ERROR    graphql.execution.utils:utils.py:155 Traceback (most recent call last):
  File "/home/dthompson/Code/personal/gardenbuilder-backend/env/lib/python3.6/site-packages/promise/promise.py", line 489, in _resolve_from_executor
    executor(resolve, reject)
  File "/home/dthompson/Code/personal/gardenbuilder-backend/env/lib/python3.6/site-packages/promise/promise.py", line 756, in executor
    return resolve(f(*args, **kwargs))
  File "/home/dthompson/Code/personal/gardenbuilder-backend/env/lib/python3.6/site-packages/graphql/execution/middleware.py", line 75, in make_it_promise
    return next(*args, **kwargs)
  File "/home/dthompson/Code/personal/gardenbuilder-backend/src/gardens/schema.py", line 43, in resolve_gardens
    raise Exception("You must be a superuser to view all gardens")
graphql.error.located_error.GraphQLLocatedError: You must be a superuser to view all gardens
======================= short test summary info ========================
FAILED gardens/tests.py::TestGraphQLQueries::test_gardens_query - Ass...

【问题讨论】:

  • 不会以超级用户通过测试发送请求吗?
  • 是的,以超级用户身份发送请求会通过测试,但我如何模拟它以进行测试?

标签: django graphql pytest graphene-python graphene-django


【解决方案1】:

您不能将上下文值直接传递给 self.query 方法。

您需要做的是创建一个测试客户端,然后提供用于测试的测试上下文值。


from graphene.test import Client
from snapshottest import TestCase

from users.models import CustomUser
from .schema import schema

class SuperUser:
    is_superuser = True

class TestContext:
    user = SuperUser()

class TestGraphQLQueries(TestCase):
    """
    Test that GraphQL queries related to gardens work and throw errors appropriately
    """

    context_value = TestContext()

    def test_gardens_query(self):
        client = Client(schema, context_value=self.context_value)
        query = (
            """
            query {
                gardens {
                    id
                    name
                    owner {
                        id
                        email
                    }
                }
            }
            """
        )
        
        self.assertMatchSnapshot(client.execute(query))

【讨论】:

    【解决方案2】:

    您可以使用 RequestFactory 以与为 Django 设置相同的方式设置石墨烯请求的用户。根据我在Testing Graphene-Django 中的回答,模式是

    from django.test import RequestFactory, TestCase
    from graphene.test import Client
    
    
    user = ... (fetch your test superuser)
    api_query = """
            query {
                gardens {
                    id
                    name
                    owner {
                        id
                        email
                    }
                }
            }
            """
    request_factory = RequestFactory()
    context_value = request_factory.get('/api/')  # or use reverse() on your API endpoint
    context_value.user = user
    client = Client(schema)
    executed = client.execute(api_query, context_value=context_value)
    output_data = executed.get('data')
    

    【讨论】:

      猜你喜欢
      • 2019-03-22
      • 2021-09-14
      • 1970-01-01
      • 2022-10-25
      • 1970-01-01
      • 1970-01-01
      • 2021-12-23
      • 2021-08-16
      • 1970-01-01
      相关资源
      最近更新 更多