Alex Rivera | Logout

Why don't my Django unittests know that MessageMiddleware is installed?

Asked 2012-08-13T16:11:12.687
44

I'm working on a Django project and am writing unittests for it. However, in a test, when I try and log a user in, I get this error:

MessageFailure: You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware

Logging in on the actual site works fine -- and a login message is displayed using the MessageMiddleware.

In my tests, if I do this:

from django.conf import settings
print settings.MIDDLEWARE_CLASSES

Then it outputs this:

('django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware')

Which appears to show the MessageMiddleware is installed when tests are run.

Is there an obvious step I'm missing?

UPDATE

After suggestions below, it does look like it's a settings thing.

I currently have settings/__init__.py like this:

try:
    from settings.development import *
except ImportError:
    pass

and settings/defaults.py containing most of the standard settings (including MIDDLEWARE_CLASSES). And then settings.development.py overrides some of those defaults like this:

from defaults import *

DEBUG = True
# etc

It looks like my dev site itself works fine, using the development settings. But although the tests seem to load the settings OK (both defaults and development) settings.DEBUG is set to False. I don't know why, or whether tha

Edit
Report

1 Answer

5

A way to solve this quite elegant is to mock the messages module using mock

Say you have a class based view named FooView in app named myapp

from django.contrib import messages
from django.views.generic import TemplateView

class FooView(TemplateView):
    def post(self, request, *args, **kwargs):
        ...
        messages.add_message(request, messages.SUCCESS, '\o/ Profit \o/')
        ...

You now can test it with

def test_successful_post(self):
    mock_messages = patch('myapp.views.FooView.messages').start()
    mock_messages.SUCCESS = success = 'super duper'
    request = self.rf.post('/', {})
    view = FooView.as_view()
    response = view(request)
    msg = _(u'\o/ Profit \o/')
    mock_messages.add_message.assert_called_with(request, success, msg)
answered 2013-02-01T12:31:53.797

Your Answer