Django测试客户端提交一个带有POST请求的表单

nle07wnf  于 2023-01-18  发布在  Go
关注(0)|答案(4)|浏览(148)

我怎样才能用Django test Client提交POST请求,这样我就可以在请求中包含表单数据了?特别是,我希望有这样的东西(灵感来自于我应该如何在Django中为表单编写测试?):

from django.tests import TestCase

class MyTests(TestCase):
    def test_forms(self):
        response = self.client.post("/my/form/", {'something':'something'})

我的端点/my/form有一些内部逻辑来处理“something”。问题是当我稍后尝试访问request.POST.get('something')时,我无法获得任何东西。我找到了一个解决方案,所以我在下面分享。

soat7uwm

soat7uwm1#

关键是在client的post方法中添加content_type,并对数据进行urlencode编码。

from urllib import urlencode

...

data = urlencode({"something": "something"})
response = self.client.post("/my/form/", data, content_type="application/x-www-form-urlencoded")

希望这对某人有帮助!

avwztpqn

avwztpqn2#

如果你使用client在旧版django上发送字典,你必须定义content_type ='application/json',因为它的内部转换无法处理字典,你还需要使用 json.dumps 方法像blob一样发送字典。

import json
from django.tests import TestCase

class MyTests(TestCase):
    def test_forms(self):
        response = self.client.post("/my/form/", json.dumps({'something':'something'}), content_type='application/json')
jgzswidk

jgzswidk3#

如果您将content_type作为application/json提供,则如果数据是dict、list或tuple,则使用json.dumps()进行序列化。默认情况下使用DjangoJSONEncoder执行序列化,并且可以通过向Client提供json_encoder参数来覆盖序列化。put()、patch()和delete()请求也会发生此序列化。

bn31dyow

bn31dyow4#

我尝试过在Django中使用Client()对POST请求进行单元测试,但是我无法让它工作(即使使用上面指定的方法)。所以这里有一个专门针对POST请求的替代方法(使用HttpRequest()):

from django.http import HttpRequest
from django.tests import TestCase
from . import views
# If a different test directory is being used to store the test files, replace the dot with the app name

class MyTests(TestCase):
    def test_forms(self):
        request = HttpRequest()
        request.method = 'POST'
        request.POST['something'] = 'something'
        request.META['HTTP_HOST'] = 'localhost'
        response = views.view_function_name(request)
        self.assertNotIn(b'Form error message', response.content)
        # make more assertions, if needed

将**view_function_name()**替换为实际的函数名。此函数向正在测试的视图发送POST请求,其中包含表单字段“something”及其对应的值。Assert语句将完全取决于测试函数的实用性。以下是一些可以使用的Assert:

  • self.assertEquals(response.status_code, 302):当表单在提交POST请求后重定向时(302是重定向的状态码),进行此Assert。
  • self.assertNotIn(b'Form error message', response.content):将“Form error message”替换为通过请求发送不正确详细信息时表单生成的错误消息。如果测试数据不正确,则测试将失败(文本将转换为字节,因为HttpResponse().content也是bytes对象)。

如果view函数也使用Django Message框架来显示表单错误消息,请在response之前包含以下内容:

from django.contrib import messages
...
request._messages = messages.storage.default_storage(request)

如果视图函数使用会话,请在响应之前包含此内容:

from importlib import import_module
from django.conf import settings
...
engine = import_module(settings.SESSION_ENGINE)
session_key = None
request.session = engine.SessionStore(session_key)

在发出请求之前,请记住应用程序可能使用的任何上下文处理器的用法。
我个人觉得这个方法更直观(和功能性)。这似乎涵盖了所有可能的关于HTTP请求和表单的测试用例。
我还想建议将每个单元测试用例分解为单独的组件,以增加覆盖率并发现代码中潜在的bug,而不是将所有用例集中在一个test_forms()中。
Harry J.W. Percival在他的书
Test-Driven Development with Python
中提到了这项技术。

相关问题