[Django]-Django: Avoid HTTP API calls while testing from django views

2👍

This is where mocking comes in. In your tests, you can use libraries to patch the parts of the code you are testing to return the results you expect for the test, bypassing what that code actually does.

You can read a good blog post about mocking in Python here.

If you are on Python 3.3 or later, the mock library is included in Python. If not, you can download it from PyPI.

The exact details of how to mock the calls you’re making will depend on what exactly your view code looks like.

👤Ben

3👍

You could override settings in your tests and then check for that setting in your view. Here are the docs to override settings.

from django.conf import settings
if not settings.TEST_API:
    # api call here

Then your test would look something like this

from django.test import TestCase, override_settings

class LoginTestCase(TestCase):

    @override_settings(TEST_API=True)
    def test_api_func(self):
        # Do test here

Since it would be fairly messy to have those all over the place I would recommend creating a mixin that would look something like this.

class SensitiveAPIMixin(object):
    def api_request(self, url, *args, **kwargs):
        from django.conf import settings
        if not settings.TEST_API:
            request = api_call(url)
            # Do api request in here
        return request

Then, through the power of multiple inheritence, your views that you need to make a request to this api call you could do something similar to this.

class View(generic.ListView, SensitiveAPIMixin):
    def get(self, request, *args, **kwargs):
        data = self.api_request('http://example.com/api1')

1👍

Ben is right on, but here’s some psuedo-ish code that might help. The patch here assumes you’re using requests, but change the path as necessary to mock out what you need.

from unittest import mock
from django.test import TestCase
from django.core.urlresolvers import reverse

class MyTestCase(TestCase):

    @mock.patch('requests.post') # this is all you need to stop the API call
    def test_my_view_that_posts_to_an_api(self, mock_get):
        response = self.client.get(reverse('my-view-name'))

        self.assertEqual('my-value', response.data['my-key'])
        # other assertions as necessary

Leave a comment