I am just learning how to unit test so I'm sure I'm not understanding some core principal.
I have custom 400 and 500 error handlers that return a template indicating the error to the user. Now, in practice, when I run my site, these work perfectly! Errors get caught and the templates get generated exactly as anticipated. The difficulty comes when I try to write unit tests for the 500 error.
What occurs: any references to a namespace (in this case, 'base') throws an error.
Traceback (most recent call last):
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/urls/base.py", line 71, in reverse
extra, resolver = resolver.namespace_dict[ns]
KeyError: 'base'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/--------/Documents/projects/--------/base/testing/test_views.py", line 50, in test_handler_renders_template_response
response = self.client.get('/500/')
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/client.py", line 836, in get
response = super().get(path, data=data, secure=secure, **extra)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/client.py", line 424, in get
return self.generic(
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/client.py", line 541, in generic
return self.request(**r)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/client.py", line 805, in request
response = self.handler(environ)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/client.py", line 153, in __call__
response = self.get_response(request)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/sentry_sdk/integrations/django/__init__.py", line 409, in sentry_patched_get_response
rv = old_get_response(self, request)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 140, in get_response
response = self._middleware_chain(request)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 57, in inner
response = response_for_exception(request, exc)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 140, in response_for_exception
response = handle_uncaught_exception(
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 185, in handle_uncaught_exception
return callback(request)
File "/home/--------/Documents/projects/--------/base/views.py", line 22, in handler500
render(request, 'base/html/templates/500.html')
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/sentry_sdk/integrations/django/templates.py", line 95, in render
return real_render(request, template_name, context, *args, **kwargs)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/shortcuts.py", line 24, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/backends/django.py", line 62, in render
return self.template.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 175, in render
return self._render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/utils.py", line 111, in instrumented_test_render
return self.nodelist.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/utils.py", line 111, in instrumented_test_render
return self.nodelist.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/loader_tags.py", line 208, in render
return template.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 177, in render
return self._render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/test/utils.py", line 111, in instrumented_test_render
return self.nodelist.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/template/defaulttags.py", line 472, in render
url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
File "/home/--------/Documents/projects/--------/venv/lib/python3.10/site-packages/django/urls/base.py", line 82, in reverse
raise NoReverseMatch("%s is not a registered namespace" % key)
django.urls.exceptions.NoReverseMatch: 'base' is not a registered namespace
Here is the template:
{% extends 'base/html/templates/base.html' %}
{% load static %}
{% block body %}
<div >
<h4 >500 Error: Server error</h4>
<p>
Something generated an error that couldn't be fixed. If you want, email me at <email address> and let me know what happened.
</p>
</div>
{% endblock body %}
Here is the unit test:
from django.test import SimpleTestCase, override_settings
from django.urls import reverse
from project.settings import ROOT_URLCONF
from django.urls import path
from django.shortcuts import render
from ..views import handler500
def raise_500(request):
return 1/0
urlpatterns = [
path('500/', raise_500),
]
handler500 = handler500
@override_settings(ROOT_URLCONF=__name__)
class Test_500(SimpleTestCase):
def test_handler_renders_template_response(self):
self.client.raise_request_exception = False
response = self.client.get('/500/')
self.assertEqual(response.status_code, 500)
self.assertTemplateUsed('base/html/templates/500.html')
If I remove the {% extends %}
tag from the template, the unit test passes! In fact, all the template tags work except for the ones that reference a "namespace"; so neither {% extends %}
nor {% url %}
tags work, but {% static %}, {% block %}, etc., are rendered as expected.
I'm not sure what's going on. To be honest it's not a big problem: to satisfy the unit test I just use a static 500 page with one hard-coded link to '/', and everything is fine. But in my effort to learn how to test properly, I'm curious as to why I'm getting these namespace errors just because I used {% extends %}
or {% url %}
in the template.
CodePudding user response:
You could be overriding your app urls.py by defining your own urlpatterns= [...]
in the test script. This would mean your usual namespace info isn't available. In that case, urlpatterns = [...]
might work better.