【问题标题】:Django AssertionError - 302 is not 302Django AssertionError - 302 不是 302
【发布时间】:2021-02-13 21:33:45
【问题描述】:

我为一个接受带有文件的 POST 请求的端点设置了一个超级简单的单元测试,并在成功上传后将用户重定向到新页面。本单元的目标是对其进行测试以确保文件上传正常。

tests.py

c = Client()
with open('replays/static/test.txt', 'r', ) as f:
    response = c.post(
        '/upload/',
        {
            'summoner': 'test user',
            'title': 'Testing title',
            'replay': f
        },
        follow=False
    )

    print(response.status_code)
    print(response.status_code == 302)
    self.assertIs(response.status_code, 302)

输出

$ python manage.py test replays
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
302
True
======================================================================
FAIL: test_create_replay (replays.tests.ReplayCreationTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/path/to/project/tests.py", line 52, in test_create_replay
    self.assertIs(response.status_code, 302)
AssertionError: 302 is not 302

----------------------------------------------------------------------
Ran 1 test in 0.173s

FAILED (failures=1)
Destroying test database for alias 'default'...

如果我在调用测试客户端的 post 方法时更改以下重定向的参数,一切都会按预期运行,response_status 为 200

tests.py - 跟随重定向

c = Client()
    with open('replays/static/test.txt', 'r', ) as f:
        response = c.post(
            '/upload/',
            {
                'summoner': 'test user',
                'title': 'Testing title',
                'replay': f
            },
            follow=True
        )

    print(response.status_code)
    print(response.status_code == 200)
    self.assertIs(response.status_code, 200)

输出

$ python manage.py test replays
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
200
True
.
----------------------------------------------------------------------
Ran 1 test in 0.196s

OK
Destroying test database for alias 'default'...

我错过了什么?这似乎不应该是断言语句的预期行为。我正在使用 Django 3.1。

【问题讨论】:

  • @ihunter2839-如果我错了请纠正我,在文件上传测试中,实际文件的上传不应该被模拟吗?
  • 在这种情况下,我希望文件完成上传,因为我正在使用需要访问密钥才能完成的外部存储,并且部分测试是确保密钥是好的。除非有更有效的方法来做到这一点?
  • @ihunter2839- 好像你正在测试两件事。身份验证和文件上传。据我所知,应该模拟 I/O 绑定调用。
  • Hrm,需要明确一点 - 没有用户身份验证,因为文件上传是公开的,并且密钥用于 S3 存储桶。如果您的意思是应用程序身份验证,那么我想您是正确的,但我不熟悉唯一测试这一点的技术。
  • @ihunter2839- 是的,我的意思是应用程序身份验证。

标签: django django-testing


【解决方案1】:

AssertIs 检查x is y,换句话说,xy 是否引用 same 对象。但是你可以有两个int 对象,它们都是302,但不是同一个对象。

你应该使用.AssertEqual(…) [Python-doc]:

self.<b>assertEqual(</b>302, response.status_code<b>)</b>

对于小整数,CPython 解释器将为 -5 到 256 构造 int 对象,因此使用 flyweight 模式

当前实现为-5256 之间的所有整数保留一个整数对象数组,当您在该范围内创建一个int 时,实际上您只是取回对现有对象的引用。

这意味着对于介于 -5 和 256 之间的int,它将引用 same 对象,对于超出该范围的值,它通常会构造一个新对象。

【讨论】:

  • 我确认 self.assertEqual 按预期工作,所以谢谢。但我不能说我理解为什么 self.assertIs 在状态为 200 的情况下有效,但在状态为 302 时失败。这两种情况的行为似乎应该相同?
  • @ihunter2839:因为小整数(通常)使用享元模式:对于高达 256 的值,它将与 int 对象组成一个小缓存。
  • @ihunter2839:见编辑。然而享元模式是一个实现细节,所以你不应该真的假设这会(总是)工作,未来的版本可以改变这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 2011-11-09
  • 2023-03-21
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
相关资源
最近更新 更多