Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django how to test if message is sent

Tags:

django

testing

I want to test if message is sent to user after submit. I'm using django.contrib.messages. Everything seems to be working during manual testing (runserver), but in unit test I don't get messages.

Code that stores message:

messages.success(request, _('Internationalized evil message.'))

Code that should test message:

from django.contrib.messages.api import get_messages

...

def test_message_should_sent_to_user(self):
    """After successful phone number submit, message should be displayed."""
    response = self.client.post(
        reverse('evil.views.evil_data_submit'), self.valid_data)
    messages = get_messages(response.request)
    self.assertNotEqual(len(messages), 0)

It looks like that no middleware is called during test client post method call.


Update after @Tisho answer

Messages should be found in response.context, even my guts say that it should work, but it doesn't. I've placed import pdb; pdb.set_trace() in django/contrib/messages/context_processors.py to see if its called during test client.post, its not.

I've double checked TEMPLATE_CONTEXT_PROCESSORS, MIDDLEWARE_CLASSES and INSTALLED_APPS - probably tomorrow I'll discover that I missed something.


Important detail

Forgot to mention that in case of successful submit view returns HttpResponseRedirect therefore response.context is empty.


Solution

View returns redirect (which has no context data), to solve that we can pass follow=True to client.post method (method suggested by @Tisho).

like image 954
aisbaa Avatar asked Jul 12 '12 15:07

aisbaa


People also ask

How do I know if my email is sent Django?

There is no way to check that a mail has actually been received. This is not because of a failing in Django, but a consequence of the way email works. If you need some form of definite delivery confirmation, you need to use something other than email.

What is assert in Django?

The assert keyword is used when debugging code. The assert keyword lets you test if a condition in your code returns True, if not, the program will raise an AssertionError. You can write a message to be written if the code returns False, check the example below.


2 Answers

During unit tests, the message could be found in

response = self.client.post(
    reverse('evil.views.evil_data_submit'), self.valid_data)
messages = response.context['messages']

If your view returns a redirect, response.context will be empty unless you pass follow=True, like so:

response = self.client.post(
    reverse('evil.views.evil_data_submit'),
    self.valid_data,
    follow=True)
like image 67
Tisho Avatar answered Sep 29 '22 00:09

Tisho


The best way I found is by using mock

http://www.voidspace.org.uk/python/mock/patch.html#patch-methods-start-and-stop

class SimpleCommentTestDirect(TestCase):

def setUp(self):
    self._patcher1 = patch('django.contrib.messages.error')
    self.mock_error = self._patcher1.start()

def tearDown(self):
    self._patcher1.stop()

def test_error_message(self):
    self.client.get('/vote/direct/unknownapp/comment/1/up/')
    self.assertEqual(self.mock_error.call_args[0][1], 'Wrong request. Model.')

BTW: There are also should be a way to get request by using mock. And by using request object get message from django.contrib.messages.get_messages

like image 36
Oduvan Avatar answered Sep 28 '22 23:09

Oduvan