Graphene: info.context is None when using test client

Created on 1 Nov 2017  路  4Comments  路  Source: graphql-python/graphene

Hi,
I upgraded to 2.x and using context from info.context. That works fine when I send regular POST request, but in tests is info.context None. I understand that request isn't available in tests, but shouldn't it be at least mocked by default?

Most helpful comment

@emilyzzz I solved it by passing context_value to client.execute explicitly.

First I create fixtures for requests. It's necessary to run them through all required middlewares:

# rf fixture is from django-pytest and make_user is own user model factory

@pytest.fixture
def rq_authenticated(rf, make_user):
    user = make_user(email='[email protected]', password='test')

    request = rf.post('/')
    SessionMiddleware().process_request(request)
    request.session.save()
    request.user = user

    return request

@pytest.fixture
def rq_anonymous(rf):
    request = rf.post('/')
    SessionMiddleware().process_request(request)
    request.session.save()
    request.user = AnonymousUser()

    return request

Test is something like:

def test_query(client, rq_authenticated):
    executed = client.execute(query, context_value=rq_authenticated)

I use rq_authenticated and rq_anonymous explicitly everywhere I check authentication (which is almost everywhere)

All 4 comments

Ran into similar issue. Upgraded to 2.0 recently, using graphene with Django.

My mutate is defined as:

class Login(graphene.Mutation):
    .....
    def mutate(root, info, **args):
        user = authenticate(
            username=args.get('username'),
            password=args.get('password'),
        )
        info.context.session['token'] = user.token    # 'info.context' is None only when running tests.

Test is py.test style, looks like this:

from graphene.test import Client
client = Client(schema)
result = client.execute(query)       # this will cause error, due to info.context is None.

@emilyzzz I solved it by passing context_value to client.execute explicitly.

First I create fixtures for requests. It's necessary to run them through all required middlewares:

# rf fixture is from django-pytest and make_user is own user model factory

@pytest.fixture
def rq_authenticated(rf, make_user):
    user = make_user(email='[email protected]', password='test')

    request = rf.post('/')
    SessionMiddleware().process_request(request)
    request.session.save()
    request.user = user

    return request

@pytest.fixture
def rq_anonymous(rf):
    request = rf.post('/')
    SessionMiddleware().process_request(request)
    request.session.save()
    request.user = AnonymousUser()

    return request

Test is something like:

def test_query(client, rq_authenticated):
    executed = client.execute(query, context_value=rq_authenticated)

I use rq_authenticated and rq_anonymous explicitly everywhere I check authentication (which is almost everywhere)

@tricoder42 I'm not sure that context should be defined by default since context_value does not have to be defined. Also it's not clear what it should be mocked to by default. In tests it should be up to the developer to pass context_value when creating the test client (e.g. client = Client(schema, context_value=request)

Closing this issue as clean up but happy to have a discussion about it if anyone feels strongly.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

japrogramer picture japrogramer  路  4Comments

dfee picture dfee  路  4Comments

lincolnq picture lincolnq  路  3Comments

danpalmer picture danpalmer  路  4Comments

Globegitter picture Globegitter  路  4Comments