pythondjangoauthenticationdjango-testingpython-social-auth

Extend social pipeline and prevent a specific function to run during tests


I'm using Python Django Social Auth and extended the pipeline with the following three steps

  1. One before the user is created (partial pipeline) requesting some data.
  2. One for the user creation (overrides the social.pipeline.user.create_user method).
  3. One after the user is created.

Here's how the pipeline currently looks like

SOCIAL_AUTH_PIPELINE = (
    'social_core.pipeline.social_auth.social_details',
    'social_core.pipeline.social_auth.social_uid',
    'social_core.pipeline.social_auth.social_user',
    'myapp.file.before_user_is_created',
    'myapp.file.create_user',
    'social_core.pipeline.social_auth.associate_user',
    'myapp.file.after_user_creation',
    'social_core.pipeline.social_auth.load_extra_data',
    'social_core.pipeline.user.user_details',
)

In order to test it, I'm following similar logic to the one used here. This is what I have

@mock.patch("social_core.backends.base.BaseAuth.request")
def test_complete(self, mock_request):
        url = reverse("social:complete", kwargs={"backend": "facebook"})
        url += "?code=2&state=1"
        mock_request.return_value.json.return_value = {"access_token": "123"}
        with mock.patch(
            "django.contrib.sessions.backends.base.SessionBase" ".set_expiry",
            side_effect=[OverflowError, None],
        ):
            response_1 = self.client.get(url)
            self.assertEqual(response_1.status_code, 302)
            self.assertEqual(response_1.url, "/before-user-is-created/")

            response_2 = self.client.post("/before-user-is-created/", {"some_keys": "some_values"})
            self.assertEqual(response_2.status_code, 302)
            self.assertEqual(response_2.url, "/social-auth/complete/facebook/")

            response_3 = self.client.post("/social-auth/complete/facebook/")
            return response_3

For step 1, I have a url (/before-user-is-created/) and a specific view. So, I get that view and I'm able to act on it when running

response_1 = self.client.get(url)

as you can see from the self.assertEqual(response_1.url, "/before-user-is-created/") and from response_2 = self.client.post("/before-user-is-created/", {"some_keys": "some_values"}).

The problem is with step 3. That is essentially a function (after_user_creation()) that calls another one (function_called())

def after_user_creation(user, *args, **kwargs):
    ...
    function_called(something_from_user)

That function is called in this part during the test (together with load_extra_data and user_details (the ones coming after it in the pipeline))

response_2 = self.client.post("/before-user-is-created/", {"some_keys": "some_values"})
...
response_3 = self.client.post("/social-auth/complete/facebook/")
...

How to prevent function_called(something_from_user) to run during tests?


Solution

  • You can patch myapp.file.function_called as usual:

    with mock.patch(
        "django.contrib.sessions.backends.base.SessionBase" ".set_expiry",
        side_effect=[OverflowError, None],
    ), mock.patch("myapp.file.function_called"):
    

    Alternatively:

    @mock.patch("myapp.file.function_called")
    @mock.patch("social_core.backends.base.BaseAuth.request")
    def test_complete(self, mock_request, mock_function_called):