Why is my view unit test giving a 301 error?

I have a pretty basic Django app in early stages of development. I want to test the views, and it is not working. More specifically it reports a 301 HTTP response, and the content is:

b''

As far as I can tell, it is not actually using the view method, but I cannot see what it is doing.

I have commented out all other URLs and views to ensure none of them are interfering, and renamed the view method to ensure it is using the right one. If I change the URL, it fails because it cannot find the path. If I change the method name it fails because it cannot find the method. So it seems to be using the right method.

However… I have changed the code in the view method to print a message, then throw an exception. If I run the server, I get the expected exception. But running the test, no method and no exception.

Here is the code in urls.py, stripped back to just the one path.

from django.urls import path
from . import views

urlpatterns = [
    path('orders/', views.order_test, name='order_test'),
]

The code in views:

def order_test(request):
    print('In order_test')
    raise Exception("Error!")

And the test:

from django.test import TestCase

class OrderViewsTests(TestCase):

    def testShow(self):
        url = '/gas_filling/orders/' + str(self.row.id)
        print(url)

        response = self.client.get(url)

        print('Done!')        
        print(response.status_code)
        print(response.content)
        print(response.context)
        
        self.assertEqual(response.status_code, 200)      

And the output (there is a test for the model which is fine; the app is called “gas_filling”):

Found 2 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
./gas_filling/orders
Done!
301
b''
[{'True': True, 'False': False, 'None': None}, {'request_path': '/gas_filling/orders', 'exception': 'Resolver404'}]
F
======================================================================
FAIL: testShow (gas_filling.tests.test_views.OrderViewsTests.testShow)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "H:\f2_db_github\gas-packing\gas_filling\tests\test_views.py", line 19, in testShow
    self.assertEqual(response.status_code, 200)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 301 != 200

----------------------------------------------------------------------
Ran 2 tests in 0.097s

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

A 301 response isn’t an “error” it’s a redirection.

In your test you’re doing this:

    url = '/gas_filling/orders/' + str(self.row.id)
    print(url)

But the output shows the URL as:

/gas_filling/orders

So I’m going to assume the actual test you’re running has this instead:

    url = '/gas_filling/orders'
    print(url)

In which case, the 301 you’re getting is because you don’t have a slash on the end of the URL in the test, so Django is redirecting to the version with a slash on the end.

(I’m assuming the urls.py you’ve provided is included from your project’s urls.py under /gas_filling/.)

Thanks, the missing slash was the issue.