How can I unit test django messages? How can I unit test django messages? python python

How can I unit test django messages?


I found a really easy approach:

response = self.client.post('/foo/')messages = list(response.context['messages'])self.assertEqual(len(messages), 1)self.assertEqual(str(messages[0]), 'my message')

If you need to check for messages on a response that has no context you can use the following:

from django.contrib.messages import get_messagesmessages = list(get_messages(response.wsgi_request))self.assertEqual(len(messages), 1)self.assertEqual(str(messages[0]), 'my message')

The fallback storage doesn't support indexing, however it is an iterable.


From django documentation:

Outside of templates, you can use get_messages()

So, you could write something like:

from django.contrib.messages import get_messages[...]messages = [m.message for m in get_messages(response.wsgi_request)]self.assertIn('My message', messages)


This works for me (displays all messages):

print [m.message for m in list(response.context['messages'])]

Also here are a couple of utility methods I have in a test class inherited from Django's TestCase. If you'd prefer to have them as functions, remove the self arguments and replace self.fail()'s with a raise.

def assert_message_count(self, response, expect_num):    """    Asserts that exactly the given number of messages have been sent.    """    actual_num = len(response.context['messages'])    if actual_num != expect_num:        self.fail('Message count was %d, expected %d' %            (actual_num, expect_num))def assert_message_contains(self, response, text, level=None):    """    Asserts that there is exactly one message containing the given text.    """    messages = response.context['messages']    matches = [m for m in messages if text in m.message]    if len(matches) == 1:        msg = matches[0]        if level is not None and msg.level != level:            self.fail('There was one matching message but with different'                'level: %s != %s' % (msg.level, level))        return    elif len(matches) == 0:        messages_str = ", ".join('"%s"' % m for m in messages)        self.fail('No message contained text "%s", messages were: %s' %            (text, messages_str))    else:        self.fail('Multiple messages contained text "%s": %s' %            (text, ", ".join(('"%s"' % m) for m in matches)))def assert_message_not_contains(self, response, text):    """ Assert that no message contains the given text. """    messages = response.context['messages']    matches = [m for m in messages if text in m.message]    if len(matches) > 0:        self.fail('Message(s) contained text "%s": %s' %            (text, ", ".join(('"%s"' % m) for m in matches)))