test client vs jinja?

84 views
Skip to first unread message

Roy Smith

unread,
Feb 5, 2021, 12:29:23 AM2/5/21
to django...@googlegroups.com
I started my current project using native django templates and now I'm converting to jinja2. For the most part, it has gone smoothly.

The surprising roadblock was that this broke all my unit tests. The issue is that django.template.backends.jinja2.Jinja2 doesn't populate response.context.

One thought I had was to patch django.shortcuts.render() with unittest.mock. That didn't work out so well.

Where I seem to be heading now is to have each of my View subclasses have a build_context() static method, put most of the logic in that, and then I can call that directly in my unit tests. This seems to be workable, but it's kind of ugly that I need to alter my production code to make it testable.

Any wisdom from people who have gone through this would be appreciated.

Benny M

unread,
Feb 5, 2021, 6:37:10 AM2/5/21
to django...@googlegroups.com
Hi Roy,

I haven’t been through this personally, but it strikes me as odd that the test can’t read the request context. On the surface it would stand to reason that if the test can’t read it, then the page wouldn’t render on browser request. Can you post an example of one of your failing tests and the accompanying failure result?

Benny

Roy Smith

unread,
Feb 10, 2021, 10:47:24 PM2/10/21
to Django users
It's a known problem.  See https://code.djangoproject.com/ticket/24622.  In short, the django template code has hooks to populate these values in the test client's response.  The jinja folks (understandably) don't want to add the same hooks.

Roy Smith

unread,
Feb 11, 2021, 2:32:31 AM2/11/21
to Django users
I've gotten back to playing with this.  What I've ended up doing is monkey-patching render to send the signal django.test.Client is expecting from the template backend.  Paraphrasing my (python 3.7) code:

from unittest.mock import patch
from django.test.signals import template_rendered
from django.shortcuts import render

class TimelineViewTest(TestCase):
    @patch('spi.views.render')
    def test_context_includes_tag_list(self, mock_render):

        def render_patch(request, template, context):
            template_rendered.send(sender=self, template=template, context=context)
            return render(request, template, context)

        mock_render.side_effect = render_patch

At least doing it this way puts all the weird stuff in my test code.  I didn't have to touch anything in my production view code (or in either django or jinja).

Roy Smith

unread,
Feb 11, 2021, 4:18:21 AM2/11/21
to Django users
Hmmm, it's not doing the templates quite right.  assertTemplateUsed() doesn't work, but I can get around that easy enough:

-        self.assertTemplateUsed(response, 'spi/sock-info.dtl')
+
+        self.assertEqual(response.templates, ['spi/sock-info.jinja'])

Reply all
Reply to author
Forward
0 new messages