Search code examples
djangodjango-testing

Django AssertionError - 302 is not 302


I have a super simple unit test set up for an endpoint that accepts POST requests with a file, and upon successful upload redirects the user to a new page. The goal of this unit test it to ensure file uploads are working properly.

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)

Output

$ 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'...

If I change the parameter for following redirects when calling the test client's post method, everything works as expected with a response_status of 200

tests.py - follow redirect

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)

Output

$ 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'...

What am I missing? It doesn't seem like this should be the expected behavior of the assertion statement. I am using Django 3.1.


Solution

  • AssertIs checks if x is y, in other words, that x and y refer to the same object. But you can have two int objects that are both 302, but not the same object.

    You should use .AssertEqual(…) [Python-doc]:

    self.assertEqual(302, response.status_code)

    For small integers, the CPython interpreter will construct int objects for -5 to 256, and thus work with a flyweight pattern:

    The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

    This means that for int between -5 and 256, it will refer to the same object, for values outside that range, it often constructs a new object.