【问题标题】:Django Test message passed in with Http404使用 Http404 传入的 Django 测试消息
【发布时间】:2020-12-21 17:38:06
【问题描述】:

我正在尝试检查我的应用是否在我的 Http404 调用旁边传递了一条消息。但是,我无法在测试中访问该消息,只能通过在 shell 中手动破解。

my_app.views.py:

from django.http import Http404
def index(request):
    raise Http404("My message")

然后在这个应用程序的测试文件中我调用:

from django.test import TestCase
from django.urls import reverse

class AppIndexView(TestCase):
    def test_index_view(self):
        response = self.client.get(reverse("my_app:index"))

        self.assertEqual(response.status_code, 404)
        # This checks

        self.assertEqual(response.context["reason"], "My message"
        # This gives: KeyError: 'reason'
        # However if I manually trace these steps I can access this key.

        self.assertContains(response, "My Message")
        # This gives: AssertionError: 404 != 200 : Couldn't
        # retrieve content: Response code was 404 (expected 200)
        # This is in accordance with the previous status_code check, so:

        self.assertContains(response, "My Message", status_code=404)
        # This gives: AssertionError: False is not true : Couldn't find 'My
        # Message' in response

我也尝试了各种版本来获取带有 response.exception、response.context.exception 等的消息,详见this question

如果我在 django 的 shell 中执行,我可以通过两种不同的方式访问该消息:

>>> from django.test import Client
>>> from django.urls import reverse
>>> from django.test.utils import setup_test_environment
>>> setup_test_environment()
>>> client=Client()
>>> response = client.get(reverse("my_app:index"))
>>> response.context["reason"]
'My Message'
>>> response.content
b'[lots of html...]<div id="info">\n    \n      <p>My Message</p>\n    \n  </div>[...some more html]

如何在我的 tests.py 中访问此消息?

【问题讨论】:

    标签: python django testing


    【解决方案1】:

    您可以通过HttpResponse 对象的content 属性访问其内容:

    >>> from django.http import HttpResponse
    >>> obj = HttpResponse('my message')
    >>> obj.content
    b'my message'
    

    因此,您应该能够在测试中将response.content 与您想要的结果进行比较:

    编辑:下面的测试将失败,因为response.content 将包含完整呈现的 HTML,其中可能包含也可能不包含原始异常消息。

    class AppIndexView(TestCase):
        def test_index_view(self):
            response = self.client.get(reverse("my_app:index"))
            self.assertEqual(response.status_code, 404)
            self.assertEqual(response.content, "My message")
    

    您能够手动解析response.context["reason"] 的原因是因为Django 可能在默认的404 模板上下文中设置了密钥reason,这不是您可以从客户端访问的内容。

    【讨论】:

    • 使用self.assertEqual(response.content, "My message") 给我一个AssertionError: b'\n&lt;!doctype html&gt;\n&lt;html lang="en"&gt;\n&lt;h[146 chars]l&gt;\n' != 'My Message',因为response 包含整个html。我想使用默认的Http404() 会提供一个模板,而不仅仅是一个简单的HttpResponse。但是使用self.assertContains(response, "My Message") 无论如何都会检查response.content 并引发我的问题中发布的AssertionError。 Django在测试时是否提供带有DEBUG=False的404页面?
    • 你是对的,我的回答是错误的。您正在测试的响应对象将始终包含呈现的 HTML,无法轻松识别原始 reason 消息,无法在 HTML 中搜索...
    猜你喜欢
    • 2021-07-09
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 2014-03-18
    • 2010-12-09
    • 2012-01-05
    相关资源
    最近更新 更多