16

I am testing a view and my test looks like:

def test_profile(self, user_id):
    user = User.objects.create_user(username="myusername", password="password", email="abc@testmail.com")
    self.client.user = user

    print(user.id)

    request = self.client.get("/account/profile/{}/".format(user_id), follow=True)
    self.assertEqual(request.status_code, 200)

Here my profile view has a login_required decorator. How can I set user to request.user?

ggorlen
  • 44,755
  • 7
  • 76
  • 106
gamer
  • 5,673
  • 13
  • 58
  • 91

5 Answers5

15

I was trying to do the same myself but found out that Django Test Client does not set the user in the request and it is not possible to set request.user while using Client any other way. I used RequestFactory to that.

def setUp(self):
    self.request_factory = RequestFactory()
    self.user = User.objects.create_user(
        username='javed', email='javed@javed.com', password='my_secret')
    
def test_my_test_method(self):
    payload = {
        'question_title_name': 'my first question title',
        'question_name': 'my first question',
        'question_tag_name': 'first, question'
    }
    request = self.request_factory.post(reverse('home'), payload)
    request.user = self.user
    response = home_page(request)

More about request factory here

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Javed
  • 5,904
  • 4
  • 46
  • 71
  • 1
    I think it's better to use a setUpTestData as @classmethod for user creation, so we can use it in all other functions in that TestClass. – Omid Estaji Sep 05 '21 at 15:19
12

Try this:

from django.test import TestCase, Client

from django.contrib.auth.models import User

class YourTestCase(TestCase):
    def test_profile(self, user_id):
        user = User.objects.create(username='testuser')
        user.set_password('12345')
        user.save()
        client = Client()
        client.login(username='testuser', password='12345')
        response = client.get("/account/profile/{}/".format(user.id), follow=True)
        self.assertEqual(response.status_code, 200)

Here, I first create the user and set the login credentials for the user. Then I create a client and login with that user. So in your views.py, when you do request.user, you will get this user.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Sarin Madarasmi
  • 526
  • 6
  • 11
2

This works:

self.client.force_authenticate(user=user)
Steig
  • 173
  • 2
  • 5
  • 1
    Perhaps the method name changed at some point, I'm using force_login https://docs.djangoproject.com/en/3.1/topics/testing/tools/#django.test.Client.force_login – lekksi Sep 23 '20 at 14:01
  • [`force_login`](https://docs.djangoproject.com/en/3.2/topics/testing/tools/#django.test.Client.force_login) is plain Django whereas DRF offers [`force_authenticate`](https://www.django-rest-framework.org/api-guide/testing/#forcing-authentication). – ggorlen Dec 10 '21 at 22:21
2

If you use django.test you can do something like that:

self.client.force_login(user)
Dainius
  • 37
  • 8
0

If you have a response, you can access response.context['user'].

If you need a response object, just call any view that will create a context, e.g. response = self.client.get('/').

arcanemachine
  • 571
  • 4
  • 9