Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: set cookie on test client?

Tags:

python

django

My Django site is set up with some middleware that on each request, checks for a cookie, and if it is not set, forwards the user elsewhere.

I now want to run some tests on the site. This is my code:

def test_contactform(self):
    response = self.client.get('/contact/')
    self.assertEqual(response.status_code, 200)
    print response
    self.assertTrue('Contact me' in response.content)

Unfortunately, this fails with:

Vary: Cookie
Content-Type: text/html; charset=utf-8
Location: http://testserver/ldap/?next=/contact/
Traceback (most recent call last):
  File "tests.py", line 43, in test_contactform
    self.assertEqual(response.status_code, 200)
AssertionError: 302 != 200

Can I either (i) set a cookie on the Django test client (and if so how) or (ii) require the Django test client to follow the redirect and test against the final page?

like image 400
simon Avatar asked Apr 07 '11 15:04

simon


3 Answers

None of the above worked for me (Django1.9, Python3.4). Found this solution here:

from django.test import TestCase    
from http.cookies import SimpleCookie


class TestViewWithCookies(TestCase):

    def test_votes(self):
        self.client.cookies = SimpleCookie({'name': 'bla'})
        response = self.client.get('/vote/2')
        self.assertEqual(response.status_code, 200)
like image 191
AnaPana Avatar answered Nov 15 '22 19:11

AnaPana


You can set cookies for test client by calling load on cookies attribute which is SimpleCookie object.

from django.core import signing

self.client.cookies.load({
    'example': '123',
    'signed_example': signing.get_cookie_signer('signed_example').sign('123')
})

Django's test client is stateful - will persist cookies between tests and will ignore expire dates. For removal, you need to manually remove cookie or create a new client. - See docs

--- For Python 3 and Django 2+

like image 33
pista329 Avatar answered Nov 15 '22 17:11

pista329


While the accepted answer is the right approach for this problem, I just want to point out that you can set cookies directly (i.e. approach number (i) as you call it), but not via the test client. Instead you need to use a RequestFactory to construct a request which you can set the cookie on, then pass that directly to the view in question.

So instead of:

response = self.client.get('/contact/')

you do:

request = RequestFactory().get('/contact/')
request.COOKIES['thing'] = 'whatever'
response = contact_view(request)

where contact_view is the view serving /contact/.

like image 11
gimboland Avatar answered Nov 15 '22 18:11

gimboland