Question

I would like to write unit tests for my Django app that is using python-social-auth. It all works great when running Django and using a browser, thanks python-social-auth!

However, I can't seem to write unit tests because I can't create an authenticated client to test with.

Has anyone done so successfully?
How did you get an authenticated client()?

I have tried this (the login returns false and does not work):

self.c = Client()
self.u = User.objects.create(username="testuser", password="password", is_staff=True, is_active=True, is_superuser=True)
self.u.save()
self.auth = UserSocialAuth(user=self.u, provider="Facebook")
self.auth.save()
self.c.login(username=self.u.username, password=self.u.password) 
Was it helpful?

Solution

Got it:

My mistake was thinking that it mattered how that Client got authenticated, for unit testing the views/endpoints oauth really doesn't need to come into play at all.

this worked for me:

    self.user = User.objects.create(username='testuser', password='12345', is_active=True, is_staff=True, is_superuser=True) 
    self.user.set_password('hello') 
    self.user.save() 
    self.user = authenticate(username='testuser', password='hello') 
    login = self.c.login(username='testuser', password='hello') 
    self.assertTrue(login)

OTHER TIPS

I have found a workaround to the issue by using the django.test.Client.force_login() method instead. With it, you need to fetch a user from the database, whose data is probably stored in a fixture, and specify the authentication backend in the second argument.

Here's the code I've used:

from random import sample

class SubscribeTestCase(TestCase):
    fixtures = (
        "auth.User.json", "social_django.UserSocialAuth.json",
        "<myapp>.CustomProfileUser.json", "<myapp>.SubscriptionPlan.json"
    )

    def test_user_logged_in(self):
        users = User.objects.all()
        user = sample(list(users), 1)[0]
        # This isn't actually used inside this method
        social_user = user.social_auth.get(provider="auth0")

        self.client.force_login(
            user, "django.contrib.auth.backends.ModelBackend"
        )
        response = self.client.get(
            reverse("<myappnamespace>:subscribe")
        )
        print(response.content)

        # Looking for a way to fetch the user after a
        # response was returned? Seems a little hard, see below

I am not sure how you can access a user in a Django unit test scenario after having received a Response object, which as the documentation observes is not the same as the usual HttpResponse used in production environments. I have done a quick research and it does look like developers aren't intended to do that. In my case I didn't need that so I didn't dig deeper.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top