Мне нужно хранить некое состояние между HTTP-запросами. Поскольку я не использую интерфейс JS, я решил использовать переменные сеанса, хранящиеся в файлах cookie. Мои настройки сеанса выглядят следующим образом:
SESSION_ENGINE = "django.contrib.sessions.backends.signed_cookies"
SESSION_COOKIE_HTTPONLY = False
Мне нужна функция, чтобы легко манипулировать одной переменной сеанса. Поскольку эта функция довольно проста, я решил использовать исключительно функциональное представление:
def set_category_filter(request, pk):
if pk == 0:
if 'filter_category_id' in request.session: # this is False during unit testing, but it's ok in a normal app run
del request.session['filter_category_id']
else:
get_object_or_404(Category, pk=pk, user=request.user)
request.session['filter_category_id'] = pk
return redirect('index')
Проблема в том, что я не могу выполнить тестовый случай, когда хочу сбросить эту переменную сеанса. Предположим, переменная сеанса filter_category_id
установлена, и я хочу сбросить ее. Когда я делаю это в своем браузере, все работает хорошо. Когда я пытаюсь сделать это через Django TestCase, происходит сбой, потому что эта переменная сеанса не передается в запрос!
class SetCategoryFilterTest(TestCase):
def setUp(self) -> None:
super().setUp()
self.fake = Faker()
self.user = User.objects.create_user(username="testuser", password="12345")
self.client.force_login(self.user)
def tearDown(self):
self.client.logout()
# ...
def test_unset_successfully(self):
"""Werify unsetting "filter_category_id" session field.
Expected: Delete "filter_category_id" when url called with parameter 0
"""
# GIVEN
session = self.client.session
session['filter_category_id'] = DUMMY_INT
session.save()
clear_arg = 0
# WHEN
self.client.get(reverse("filter_tasks_by_category", args=[clear_arg]))
# THEN
self.assertFalse("filter_category_id" in session)
Как вы видите, я пытаюсь предположить в тесте, что упомянутый сеанс переменная уже установлена. Затем я пытаюсь удалить, но есть две проблемы:
Во время отладки условие if 'filter_category_id' in request.session
равно False
, поэтому переменная сеанса не сбрасывается.
После того, как запрос выполнен и выполнение кода возвращается к тестовому сценарию, переменная сеанса, установленная в начале тестового примера, все еще существует, поэтому тест не пройден.
Я пытался следовать правилу из документации , что нам нужно сохранить сеанс в переменной до изменения и вызвать save()
после. Но это не помогло. Кроме того, я где-то читал, что лучше сделать еще один запрос или хотя бы login()
, чтобы установить объект сеанса. Но, как вы видите в методе setUp()
, вход в систему уже выполнен.
Это также не помогает, когда я пытаюсь выполнить другой запрос к , гарантирующему , что сеанс был создан:
def test_unset_successfully(self):
"""Werify unsetting "filter_category_id" session field.
Expected: Delete "filter_category_id" when url called with parameter 0
"""
# GIVEN
category = Category.objects.create(user=self.user, name=self.fake.name())
self.client.get(reverse("filter_tasks_by_category", args=[category.id]))
session = self.client.session
session['filter_category_id'] = DUMMY_INT
session.save()
clear_arg = 0
# WHEN
self.client.get(reverse("filter_tasks_by_category", args=[clear_arg]))
# THEN
self.assertFalse("filter_category_id" in session)
Этот код не только странный, но и не подтверждает утверждение о том, что мне нужно сначала сделать запрос перед доступом к объекту сеанса.
Знаете ли вы, как справиться с этой ситуацией? По сути, все, что я хочу сделать, - это установить переменную сеанса и передать ее с запросом на мой взгляд.