Testing custom Django middleware without using Django itself

The problem is that you are not calling neither the constructor of MyMiddleware neither invoking the __call__ magic method by invoking the instance of a MyMiddleware object.

There are many ways to test the behaviour that you described, I can think of this one:

First, I slightly modified your example to be self contained:

class MyMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        request.new_attribute = some_function_returning_some_object()
        response = self.get_response(request)
        return response

def some_function_returning_some_object():
    return 'whatever'

Next, I created the tests by actually creating the Middleware object and invoking the newly created object as it was a function (so __call__ is run)

from mock import patch, Mock
from middle import MyMiddleware
import unittest


class TestMiddleware(unittest.TestCase):

    @patch('middle.MyMiddleware')
    def test_init(self, my_middleware_mock):
        my_middleware = MyMiddleware('response')
        assert(my_middleware.get_response) == 'response'

    def test_mymiddleware(self):
        request = Mock()
        my_middleware = MyMiddleware(Mock())
        # CALL MIDDLEWARE ON REQUEST HERE
        my_middleware(request)
        assert request.new_attribute == 'whatever'

Here there are some useful links:

  • Difference between __call__ and __init__ in another SO question: __init__ or __call__?

  • Where to patch from the python docs: https://docs.python.org/3/library/unittest.mock.html#where-to-patch

  • pytest docs: http://docs.pytest.org/en/latest/contents.html

  • ipdb intro, useful for debugging: https://www.safaribooksonline.com/blog/2014/11/18/intro-python-debugger/