2013-04-22 43 views
19

Tôi đã viết bài kiểm tra cho một trong các ứng dụng django của mình và đã tìm cách giải quyết vấn đề này trong một thời gian ngắn. Tôi có chế độ xem gửi thư bằng cách sử dụng django.contrib.messages cho các trường hợp khác nhau. Giao diện trông giống như sau.Kiểm tra Django - kiểm tra tin nhắn cho chế độ xem chuyển hướng

from django.contrib import messages 
from django.shortcuts import redirect 

import custom_messages 

def some_view(request): 
    """ This is a sample view for testing purposes. 
    """ 

    some_condition = models.SomeModel.objects.get_or_none(
     condition=some_condition) 
    if some_condition: 
     messages.success(request, custom_message.SUCCESS) 
    else: 
     messages.error(request, custom_message.ERROR) 
    redirect(some_other_view) 

Bây giờ, trong khi thử nghiệm phản ứng này xem client.get 's không chứa các từ điển context chứa messages như quan điểm này sử dụng một chuyển hướng. Đối với các chế độ xem hiển thị mẫu, chúng tôi có thể truy cập vào danh sách thư bằng cách sử dụng messages = response.context.get('messages'). Làm cách nào để chúng tôi có thể truy cập messages cho chế độ xem chuyển hướng?

+0

Không chắc chắn nếu điều này sẽ phù hợp với nhu cầu của bạn nhưng bạn có thể vượt qua được biến để xác định những gì đã xảy ra: 'chuyển hướng (ngược (some_other_view) + '? user_added = true') ' –

+0

Tôi thực sự đã thử nghiệm điều kiện đang được sử dụng trong khung nhìn trong bài kiểm tra của tôi. Ở đây tôi đang nói về kiểm tra một cách rõ ràng thông điệp đã được gửi đi. – Amyth

Trả lời

31

Sử dụng tùy chọn follow=True trong cuộc gọi client.get() và khách hàng sẽ thực hiện theo chuyển hướng. Sau đó, bạn có thể kiểm tra xem thư có trong ngữ cảnh của chế độ xem bạn đã chuyển hướng đến hay không.

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

Cảm ơn, điều đó đã hiệu quả. Mặc dù, việc sử dụng 'follow = True' sẽ thay đổi mã chuyển hướng dự kiến ​​từ' 302' thành '200' khi nó theo sau chế độ xem được chuyển hướng. – Amyth

+0

Có, theo chuyển hướng có nghĩa là phản hồi có mã trạng thái 200. Có ['assertRedirects'] (https://docs.djangoproject.com/en/1.5/topics/testing/overview/#django.test.TestCase .assertRedirects) phương pháp mà bạn có thể sử dụng để kiểm tra chuyển hướng. – Alasdair

+0

yup, đó là những gì tôi đang sử dụng bây giờ :) – Amyth

1

Nếu chế độ xem của bạn đang chuyển hướng và bạn sử dụng follow=true trong yêu cầu của bạn cho khách hàng thử nghiệm ở trên không hoạt động. Tôi đã kết thúc viết một hàm trợ giúp để nhận thông điệp đầu tiên (và trong trường hợp của tôi, chỉ) được gửi cùng với câu trả lời.

@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 

Bạn bao gồm này trong lớp thử nghiệm của bạn và sử dụng nó như thế này:

message = self.getmessage(response) 

đâu response là những gì bạn nhận lại từ một get hoặc post đến một Client.

Đây là một chút mong manh nhưng hy vọng nó giúp người khác tiết kiệm thời gian.

+2

Bạn không cần danh sách đó, chỉ cần sử dụng danh sách (tin nhắn) hoặc tuple (tin nhắn). – bbrik

1

Tôi gặp sự cố tương tự khi sử dụng ứng dụng của bên thứ 3.

Nếu bạn muốn nhận được tin nhắn từ một quan điểm cho rằng trả về một HttpResponseRedict (từ mà bạn không thể truy cập vào ngữ cảnh) từ bên trong cái nhìn khác, bạn có thể sử dụng get_messages(request)

from django.contrib.messages import get_messages 

storage = get_messages(request) 
for message in storage: 
    do_something_with_the_message(message) 

này xóa lưu trữ thông điệp Mặc dù vậy, vì vậy nếu bạn muốn truy cập các thông điệp từ một mẫu sau này, thêm:

storage.used = False 
4

bạn có thể sử dụng get_messages() với response.wsgi_request như thế này (thử nghiệm trong 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

Điều này làm việc cho tôi, trong khi phương pháp của Alasdair không hiển thị bất kỳ tin nhắn nào. Tôi đang ở Django 1.11. –

0

Alternative phương pháp chế giễu tin nhắn (không cần phải làm theo chuyển hướng):

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...