How to access request.user while testing?

2019-07-03 10:54发布

问题:

I just moved from Django 1.3.1 to Django 1.4. Right after doing so, a real big number of my tests started to raise these errors:

Traceback (most recent call last):
  File "/Volumes/Data/ADay/Website/Backend/(trunk)/project/tests/templatetags.py", line 406, in setUp
    self.context = template.RequestContext(self.request)
  File "/Library/Python/2.6/site-packages/django/template/context.py", line 176, in __init__
    self.update(processor(request))
  File "/Volumes/Data/ADay/Website/Backend/(trunk)/project/social_auth/context_processors.py", line 21, in social_auth_by_type_backends
    data = backends_data(request.user)
AttributeError: 'WSGIRequest' object has no attribute 'user'

All those errors refer to django-social-auth context processors, which tries to get request.user to build the request context:

def social_auth_by_type_backends(request):
    """Load Social Auth current user data to context.
    Will add a output from backends_data to context under social_auth key where
    each entry will be grouped by backend type (openid, oauth, oauth2).
    """
    data = backends_data(request.user)
    data['backends'] = group_backend_by_type(data['backends'])
    data['not_associated'] = group_backend_by_type(data['not_associated'])
    data['associated'] = group_backend_by_type(data['associated'],
    key=lambda assoc: assoc.provider)
    return {'social_auth': data}

Doesn't Django pass the request to the functions while building the request context? I don't think that's it, somebody of the social-auth team would probably have found such an issue by now.

edit:

I first thought it would be some issue with a deprecated context_processor, but i checked and they should all be up to date:

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.messages.context_processors.messages',
    "django.contrib.auth.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.static",
    "django.contrib.messages.context_processors.messages",
    'django.core.context_processors.request',
    'pages.context_processors.media',
    'social_auth.context_processors.social_auth_by_type_backends',
    )

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

edit2:

Ok, as the site continues to work, this probably is a problem with my test code. Here it is:

def setUp(self):
    self.factory = RequestFactory()
    # create an initial request including session data        
    self.response = self.client.get('/')
    self.request = self.factory.get("/") #any valid url will do, i just need a request
    self.request.session = self.client.session

    self.context = template.RequestContext(self.request)

The last line is then provoking the error. As it is in the setUp() function of my TestCase, it starts to raise that exceptions all over my tests. Why is this not working in Django 1.4 anymore?

回答1:

In case somebody finds this: requests created with the RequestFactory appear not to return a request.user when using RequestContext(request) on them, even when "django.contrib.auth.context_processors.auth" is installed. But passing a user to the request yourself before using RequestContext(request) works fine:

class SampleTestCase(TestCase):
    fixtures = ['user_fixture.json']

    def test_only_a_sample(self):
        request.user = User.objects.get(pk=1)
        self.context = RequestContext(request)
        # some tests here

This is the code that finally worked for me.

Edit: request can be used via,

from django.test.client import RequestFactory 

# code suppressed 
def setUp(self):
    self.factory = RequestFactory()

and used in

def test_only_a_sample(self):
    request = self.factory.get('/')        # or any other methods
    request.user = User.objects.get(pk=1)
# code follows


回答2:

I needed an authenticated user for testing a privileged view. I needed to get context back in the response. RequestFactory works but it gets an HttpReponse which does not include context.

This is what I did and it worked.

class MyTestCase(TestCase):
    def setUp(self):
        self.client.login(username='user@myorg.com', password='Secret')

    def test_create_event(self):
        print("Testing create...")
        response = self.client.post('/event/new_event/', form_data_dict)
        self.assertEqual(response.status_code, 200)
        event_id = response.context['event'].event_id