Django Testing - check messages for a view that redirects

后端 未结 5 865
我在风中等你
我在风中等你 2021-02-02 10:16

I have been writing tests for one of my django applications and have been looking to get around this problem for quite some time now. I have a view that sends messages using

相关标签:
5条回答
  • 2021-02-02 10:28

    If your views are redirecting and you use follow=true in your request to the test client the above doesn't work. I ended up writing a helper function to get the first (and in my case, only) message sent with the response.

    @classmethod
    def getmessage(cls, response):
        """Helper method to return message from response """
        for c in response.context:
            message = [m for m in c.get('messages')][0]
            if message:
                return message
    

    You include this within your test class and use it like this:

    message = self.getmessage(response)
    

    Where response is what you get back from a get or post to a Client.

    This is a little fragile but hopefully it saves someone else some time.

    0 讨论(0)
  • 2021-02-02 10:31

    You can use get_messages() with response.wsgi_request like this (tested in Django 1.10):

    from django.contrib.messages import get_messages  
    ...
    def test_view(self):
        response = self.client.get('/some-url/') # you don't need follow=True
        self.assertRedirects(response, '/some-other-url/')
        # each element is an instance of  django.contrib.messages.storage.base.Message
        all_messages = [msg for msg in get_messages(response.wsgi_request)]
    
        # here's how you test the first message
        self.assertEqual(all_messages[0].tags, "success")
        self.assertEqual(all_messages[0].message, "you have done well")
    
    0 讨论(0)
  • 2021-02-02 10:34

    I had the same problem when using a 3rd party app.

    If you want to get the messages from a view that returns an HttpResponseRedict (from which you can't access the context) from within another view, you can use get_messages(request)

    from django.contrib.messages import get_messages  
    
    storage = get_messages(request)  
    for message in storage:  
        do_something_with_the_message(message)  
    

    This clears the message storage though, so if you want to access the messages from a template later on, add:

    storage.used = False
    
    0 讨论(0)
  • 2021-02-02 10:37

    Use the follow=True option in the client.get() call, and the client will follow the redirect. You can then test that the message is in the context of the view you redirected to.

    def test_some_view(self):
        # use follow=True to follow redirect
        response = self.client.get('/some-url/', follow=True)
    
        # don't really need to check status code because assertRedirects will check it
        self.assertEqual(response.status_code, 200)
        self.assertRedirects(response, '/some-other-url/')
    
        # get message from context and check that expected text is there
        message = list(response.context.get('messages'))[0]
        self.assertEqual(message.tags, "success")
        self.assertTrue("success text" in message.message)
    
    0 讨论(0)
  • 2021-02-02 10:37

    Alternative method mocking messages (doesn't need to follow redirect):

    from mock import ANY, patch
    from django.contrib import messages
    
    @patch('myapp.views.messages.add_message')
    def test_some_view(self, mock_add_message):
        r = self.client.get('/some-url/')
        mock_add_message.assert_called_once_with(ANY, messages.ERROR, 'Expected message.')  # or assert_called_with, assert_has_calls...
    
    0 讨论(0)
提交回复
热议问题