单元测试 Django JSON 视图
Posted
技术标签:
【中文标题】单元测试 Django JSON 视图【英文标题】:Unit testing Django JSON View 【发布时间】:2011-06-15 05:35:39 【问题描述】:我正在尝试为一些 Django json_view 视图编写一些单元测试,但我无法将 json_string 传递给视图。我昨天发布了一个有关从 JS 将 json 字符串传递给 Django 视图的相关问题,问题是在我的 JS 中我只是传递了 json 字符串,我需要将字符串作为对象的属性传递,因为我未能做到这一点,字符串被视为结果查询字典的键。我又遇到了类似的问题,只是这次它是对 Django View 的 Django 单元测试。这是我的代码的简化版本,它产生相同的结果。
class MyTestCase(TestCase):
def setUp(self):
self.u = User.objects.create_user('test','test','test')
self.u.is_active = True
self.u.save()
self.client.login(username='test',password='test')
def test_create_object_from_form(self):
"""Test the creation of the Instance from the form data."""
import json
json_string json.dumps('resource':'type':'book','author':'John Doe')
print(json_string)
response = self.client.post(reverse('ajax_view'),
'form':json_string,'json')
self.assetNotContains(response,'error')
视图看起来像这样
@json_view
def ajax_view(request):
"""Process the incoming form data."""
if request.method == 'POST':
print(request.POST)
form_data = json.loads(request.POST['form'])
resource_data = form_data['resource']
form = MyUserForm(resource_data)
if form.is_valid():
...
这是运行测试时两个打印语句产生的结果。 json_string 是
"resource": "type": "book", "author": "John Doe"
查询字典看起来像
<QueryDict: u'\'form\': \'"resource": "type": "book", "author": "John Doe"\'': [u'']>
我完全是 JS 和 ajax 的新手,所以不要担心伤害我的自尊心,答案可能很接近它可能会跳起来咬我。
【问题讨论】:
【参考方案1】:最终编辑
我最初声明标题 HTTP_X_REQUESTED_WITH='XMLHttpRequest'
在 post 调用中是必需的,但目前在测试中这是错误的。此标头对于 csrf 中间件是必需的,但 csrf 在测试中被禁用。但是,即使中间件禁用 csrf,我仍然认为进行测试是一个好习惯,因为大多数 javascript 库在执行 ajax 时已经默认传递了此标头。此外,如果另一段未被禁用的代码曾经使用过 is_ajax 方法,则您无需花费数小时调试单元测试来确定缺少标头。
问题出在内容类型上,因为当 django 得到一个不同于 text/html
的值时,它不使用默认的发布数据处理,即像在查询中那样格式化您的数据:@987654323 @ 例如。
那么固定的代码就是:
response = self.client.post(reverse('ajax_view'),
'form':json_string,
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
这是我自己的使用方法:
post_data =
"jsonrpc" : "2.0", "method": method, "params" : params, "id" : id
return client.post('/api/json/',
json.dumps(post_data), "text/json",
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
做一些json-rpc。请注意,由于我传递的内容类型与默认值不同,因此我的数据在发布请求中按原样传递。
【讨论】:
即使添加了标头“XMLHttpRequest”,我仍然会在查询字典的关键位置获得 JSON 字符串。 删除您如何使用 client.post 的第二个示例,我会将其标记为答案,第二个示例包含我创建帖子要解决的问题。 嗯,抱歉,第二个示例来自我的代码库,与我的 json 装饰器完美配合。请记住,我正在做的 json-rpc 与您的用例不同。 如果它可以帮助其他人,我正在研究 django-piston API,发现它默认拒绝'text/json',但接受'application/json【参考方案2】:感谢@Eric_Fortin 让我打开标题,但是它并没有解决我使用“client.post”的格式错误的查询字典的问题。一旦我使用 XMLHttpRequest 标头从 POST 更改为 GET,我的查询字典就会变得狭窄。这是当前的解决方案:
response = self.client.get(reverse('ajax_view'),
'form':json_string,'json',
HTTP_X_REQUESTED_WITH='XMLHttpRequest')
这只是部分答案,因为此请求将更改服务器上的数据,并且应该是 POST 而不是 GET。
编辑:
这是我的测试中用于通过 POST 将 JSON 字符串传递到我的视图的最终代码:
response = self.client.post(reverse('ajax_view'),
'form':json.dumps(json_dict))
现在从视图中打印显示查询字典格式正确。
<QueryDict: u'form': [u'"resource": "status": "reviewed", "name": "Resource Test", "description": "Unit Test"']>
我在与我的一位同事修补时找到了答案,删除 content_type 'json' 修复了格式错误的查询字典。正在测试的视图不使用或调用“HttpRequest.is_ajax()”,发送标头 XMLHttpRequest 对我的问题没有影响,尽管包含标头将构成良好的形式,因为这篇文章是一个 ajax 请求.
【讨论】:
错了,它也适用于 post。查看我编辑的回复。 尽管如此,即使更改代码以便将 json 字符串直接作为 'post' 方法的 'data' 参数提供,我的查询字典仍然会在我的 'view' 中与 json 字符串一起出现在关键。将方法从“post”更改为“get”并将引用的 json_string 作为字典的值,查询字典的结构正确。我坚持我的回应。 编辑了我的答案以解释问题并详细说明解决方案。 我承认标头的发送是良好的形式,因为这篇文章是一个 ajax 请求,尽管包含标头对我的问题没有影响,即查询字典的格式错误。仅提供 json_string 作为“client.post”方法的第二个参数会导致查询字典格式错误。当 content_type 设置为 'text/json' 或只是 'json' 时,'client.post' 生成的查询字典也会出现格式错误。以上是关于单元测试 Django JSON 视图的主要内容,如果未能解决你的问题,请参考以下文章