[英]Django test Client submitting a form with a POST request
如何使用 Django 测试客户端提交 POST 请求,以便在其中包含表单数据? 特别是,我想要类似的东西(灵感来自How should I write tests for Forms in Django? ):
from django.tests import TestCase
class MyTests(TestCase):
def test_forms(self):
response = self.client.post("/my/form/", {'something':'something'})
我的端点 /my/form 有一些内部逻辑来处理“某事”。 问题是,当稍后尝试访问 request.POST.get('something') 时,我什么也得不到。 我找到了解决方案,所以我在下面分享。
关键是在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")
希望这可以帮助某人!
如果您使用客户端在旧 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')
如果您提供 content_type 作为application/json
,并且数据是字典、列表或元组,则使用json.dumps()
序列化数据。 默认情况下使用DjangoJSONEncoder
执行序列化,并且可以通过向Client
提供json_encoder
参数来覆盖。 这种序列化也适用于 put()、patch() 和 delete() 请求。
我已经尝试使用Client()对 Django 中的 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()替换为实际的 function 名称。 此 function 向正在使用表单字段“某物”及其对应值进行测试的视图发送 POST 请求。 然而,断言语句将完全取决于测试函数的效用。 以下是一些可能会用到的断言:
self.assertEquals(response.status_code, 302)
:当表单在提交 POST 请求时进行重定向(302 是重定向的状态代码)时进行此断言。 在这里阅读更多相关信息。self.assertNotIn(b'Form error message', response.content)
:将'Form error message'替换为当通过请求发送不正确的详细信息时表单生成的错误消息。 如果测试数据不正确(文本将转换为字节,因为HttpResponse().content也是字节 object),测试将失败。如果视图 function 也使用 Django 消息框架来显示表单错误消息,请在响应之前包含以下内容:
from django.contrib import messages
...
request._messages = messages.storage.default_storage(request)
如果视图 function 使用会话,请在响应之前包含此内容:
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 请求和 forms 的所有可能的测试用例。
我还想建议可以将每个单元测试用例分解为单独的组件,以增加覆盖率并发现代码中的潜在错误,而不是将所有用例集中在一个test_forms()中。
Harry JW Percival 在他的书Test-Driven Development with Python中提到了这种技术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.