Проблема с тестированием сообщений в Django 5 CreateView
Я пишу юнит-тесты приложения для каталога электронных книг в Django 5. Страница создания книги использует встроенный CreateView. Код класса выглядит следующим образом:
class BookCreate(SuccessMessageMixin, PermissionRequiredMixin, CreateView):
model = Book
fields = ['title', 'author', 'genre', 'publisher', 'pages', 'cover', 'summary']
template_name = 'books/add_book.html'
permission_required = 'catalog.add_book'
permission_denied_message = 'Not enough permissions to add a book'
success_message = 'Book successfully added'
success_url = reverse_lazy('add-book')
Работает это следующим образом: пользователь заполняет данные книги, нажимает кнопку submit, затем происходит перенаправление на ту же страницу, плюс на странице выводится сообщение, указанное в атрибуте success_message класса
Для тестирования я использую MessagesTestMixin, как описано в документации Django. Вот код юнит-теста:
class TestBookCreateView(MessagesTestMixin, TestCase):
@classmethod
def setUpTestData(cls):
cls.test_user = User.objects.create_user(
email='john123@gmail.com',
username='John',
password='Fiesta123'
)
cls.add_book_permission = Permission.objects.get(codename='add_book')
def setUp(self):
login = self.client.login(username='Ivan', password='Fiesta123')
self.test_user.user_permissions.set([self.add_book_permission])
def test_if_view_success_message_attached(self):
author = Author.objects.create(
first_name='Charles',
last_name='Dickens'
)
genre = Genre.objects.create(
genre='Novel'
)
book_data = {
'title': 'Great Expectations',
'author': author,
'genre': genre
}
response = self.client.post(reverse('add-book'), data=book_data, follow=True)
self.assertMessages(response, 'Book successfully added')
Тест провален, в результатах вместо сообщения я вижу пустой список. Однако в приложении сообщение успешно передается в шаблон страницы, и я вижу его на странице после создания книги. Бэкенд хранилища сообщений в settings.py явно не задан, поэтому приложение использует storage.fallback.FallbackStorage, предоставляемый по умолчанию.
Так что же может быть проблемой в этом случае и вообще, каковы хорошие практики для тестирования сообщений в Django CBV?
Посмотрите на определение MessagesTestMixin.
class MessagesTestMixin:
def assertMessages(self, response, expected_messages, *, ordered=True):
request_messages = list(get_messages(response.wsgi_request))
assertion = self.assertEqual if ordered else self.assertCountEqual
assertion(request_messages, expected_messages)
Он просто сравнивает сообщения с помощью assertEqual
(одинаковое содержимое, одинаковый порядок) или assertCountEqual
(одинаковое содержимое, но в любом порядке) с тем, что вы передадите. Сообщения хранятся в виде списка экземпляров django.contrib.messages.storage.base.Message,
поэтому, чтобы утверждение было истинным, вы должны построить эквивалентный список.
from django.contrib import messages
from django.contrib.messages.test import MessagesTestMixin
class TestBookCreateView(MessagesTestMixin, TestCase):
def test_if_view_success_message_attached(self):
# ...
self.assertMessages(response, [
messages.Message(messages.SUCCESS, 'Book successfully added'),
])
(Я предположил, что ваше сообщение было сообщением об успехе. возможные константы: DEBUG, INFO, SUCCESS, WARNING и ERROR.)