Testing request.resolver_match in a Django context_processor

Viewed 1582

I have a Django context processor that puts the name of the current URL into the template context:

def url_name(request):
    url_name = False
    if request.resolver_match:
        url_name = request.resolver_match.url_name
    return {"url_name": url_name}

This works - if I visit / then {{ url_name }} in the template will display "home" because I have a URL pattern like:

path("", HomeView.as_view(), name="home"),

I would like to write a unittest for this context processor. I could do it like this:

from django.test import Client, RequestFactory, TestCase
from myapp.context_processors import url_name

class URLNameTestCase(TestCase):
    def test_url_name(self):
        response = Client().get("/")
        self.assertEqual(response.context["url_name"], "home")

That succeeds, but I'd like to unitttest the url_name() method on its own, outside of the response cycle.

I've tried this:

class URLNameTestCase(TestCase):
    def test_url_name(self):
        request = RequestFactory().get("/")
        context = url_name(request)
        self.assertEqual(context["url_name"], "home")

But that fails because, in this situation, within url_name(), request.resolver_match is None. Why is that?

1 Answers

since you try to get urlname by urlpath you should link your request with some view, you can do it to set "resolver_match" attribute like that:

from django.urls import resolve

...

class URLNameTestCase(TestCase):
    def test_url_name(self):
        request = RequestFactory().get("/")
        request.resolver_match = resolve("/")
...

You create a request using a RequestFactory but it doesn't mean that your request is linked with any view, to link your request with some view you need to set resolver_match to your request.

Read more:

Link 1

Link 2

Related