Тесты Django не выводят Сообщения при рендеринге шаблона

Я не могу создать модульный тест для проверки правильности отображения сообщений в моем шаблоне. В соответствии с моим шаблоном, я не получаю никакого вывода, где сообщения должны быть перечислены.

Я использую pytest 6.2.5 и Django 3.1.13, если это поможет. Вот мой тестовый код:

import pytest
from django.contrib import messages
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory
from django.views.generic import TemplateView

pytestmark = pytest.mark.django_db

class TestBaseTemplate:
    def test_messages_middleware(self):
        request = RequestFactory().get("/")
        view = TemplateView.as_view(template_name="base.html")

        middleware1 = SessionMiddleware()
        middleware1.process_request(request)
        request.session.save()

        middleware2 = MessageMiddleware()
        middleware2.process_request(request)

        foobar_msg = "Hello, world!"
        messages.info(request, foobar_msg)

        request.session.save()
        response = view(request)

        response.render()
        content = response.content.decode("utf-8")

        # This assert fails
        assert foobar_msg in content 

Мой блок сообщений в шаблоне (base.html) прямолинеен (и действительно работает в представлениях, которые отправляют сообщения):

  {% if messages %}
  <div>
    {% for message in messages %}
    <p>{{ message }}</p>
    {% endfor %}
  </div>
  {% endif %}

Я могу видеть через отладку, что прежде чем вы дойдете до рендеринга ответа, сообщение "Hello, world!" отмечается должным образом в запросе через промежуточное ПО Session/Message, оно просто не рендерится в ответе.

Есть идеи, что я упускаю? Нужно ли мне сделать что-то с контекстным препроцессором перед рендерингом содержимого?

Заранее спасибо за любой совет!

Возможно, существует более простой метод, но для меня хитрость заключалась в том, чтобы явно включить сообщения в контекст представления.

Вот как мне удалось заставить представление правильно отображать сообщения. Обратите внимание, что я использую pytest, со стандартным RequestFactory fixture. Должно быть довольно тривиально преобразовать этот код в парадигму unittest.

from typing import Any

import pytest
from django.contrib import messages
from django.contrib.messages.middleware import MessageMiddleware
from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory
from django.views.generic import TemplateView


pytestmark = pytest.mark.django_db


class TestTemplateMessages:
    """Tests for the messages rendering in template."""

    class SampleTemplate(TemplateView):
        """Template for testing."""

        template_name = "frame_with_messages_block.html"

        def __init__(self, **kwargs: Any) -> None:
            """Setup request middleware."""
            super().__init__(**kwargs)
            middleware1 = SessionMiddleware()
            middleware1.process_request(self.request)

            middleware2 = MessageMiddleware()
            middleware2.process_request(self.request)

            self.request.session.save()

        def get_context_data(self, **kwargs: str) -> dict[str, Any]:
            """Add current user to context."""
            context = super().get_context_data(**kwargs)
            context["messages"] = messages.get_messages(self.request)
            return context

    def test_messages_middleware(self, rf: RequestFactory) -> None:
        """Test messages are rendering properly in templates."""
        request = rf.get("/")

        info_message = "Hello, world!"
        error_message = "Hello, error?"
        expected_messages = [info_message, error_message]

        view = self.SampleTemplate(request=request)
        messages.info(request, info_message)
        messages.error(request, error_message)

        # Test messages are part of the request middleware
        actual_messages = [str(m) for m in messages.get_messages(request)]
        assert actual_messages == expected_messages

        # Test messages are present in the response HTML
        response = view.get(request)
        response.render()  # type: ignore
        content = response.content.decode("utf-8")
        for message in expected_messages:
            assert message in content
Вернуться на верх