为了账号安全,请及时绑定邮箱和手机立即绑定

Django csrf 令牌正在修改预期输出并导致单元测试失败

Django csrf 令牌正在修改预期输出并导致单元测试失败

交互式爱情 2021-11-09 14:55:39
我目前正在使用 Python 完成 Harry Percival 的测试驱动开发,一旦我将 {% csrf_token %} 添加到我的 html 模板,我就会遇到响应问题。由于这是测试驱动的开发,因此有几个单元测试失败。当我删除 {% csrf_token %} 时,我通过了测试。当它存在于代码中时,它会修改响应以包含意外的行<input type="hidden" name="csrfmiddlewaretoken" value="WaPf57...">出现在原始行下方“<body>    <h1>Your To-Do List</h1>        <form method="POST">            <input name="item_text" id="id_new_item" placeholder="Enter a to-do item" />            {% csrf_token %}        </form>        <table id="id_list_table">            <tr><td>{{ new_item_text }}</td></tr>        </table></body>在下面的单元测试中,我已将实际和预期结果打印到我的控制台,并且我收到了另一行带有 csrfmiddleware 令牌的行。def test_home_page_returns_correct_html(self):    request = HttpRequest()    response = home_page(request)    expected_html = render_to_string('home.html')    print('response: ', response.content.decode())    print('expected: ', expected_html)    self.assertEqual(response.content.decode(), expected_html)有没有办法从响应中删除它,或者我应该修改测试以使其包含所有预期的 HTML 并忽略“隐藏的”csrfmiddlewaretoken?
查看完整描述

2 回答

?
呼唤远方

TA贡献1856条经验 获得超11个赞

很棒的书,可以用来学习 Django!您的错误来源基于 csrf_token 标签的功能,可以在此处找到有关其工作原理的文档。简而言之,每个会话都有自己的 csrf 令牌,以确保请求来自您的网页本身,而不仅仅是从其他地方发布到您的服务器。考虑到这一点,对页面的请求和呈现为字符串的模板应该具有不同的内容。

你会在那本书中看到很多的一点是问自己这个测试是什么?对于这种情况,您似乎想检查所呈现的模板是否是您期望的模板,为此您可能希望对reponse.templates而不是 进行断言response.content.decode

如果您遵循该建议,它将最终看起来像:

    self.assertEqual(response.templates[0].name, 'home.html')


查看完整回答
反对 回复 2021-11-09
?
HUX布斯

TA贡献1876条经验 获得超6个赞

解决方案是模拟令牌生成函数,以便在需要比较输出的相等性时它具有可预测的值。


例如,下面的代码块将确保 html 输出包含<input type="hidden" name="csrfmiddlewaretoken" value="predicabletoken">而不是随机令牌字符串。


from unittest import mock


from django.test import TestCase



@mock.patch('django.template.context_processors.get_token', mock.Mock(return_value='predicabletoken'))

class HomeTests(TestCase):

  def test_home_page_returns_correct_html(self):

    request = HttpRequest()

    response = home_page(request)

    expected_html = render_to_string('home.html')

    print('response: ', response.content.decode())

    print('expected: ', expected_html)

    self.assertEqual(response.content.decode(), expected_html)


查看完整回答
反对 回复 2021-11-09
  • 2 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信