Счетчик Mocked Redis не увеличивается между запросами для разных пользователей.Python

Программы на Python
Anonymous
Счетчик Mocked Redis не увеличивается между запросами для разных пользователей.

Сообщение Anonymous »

Я тестирую представление Django, которое увеличивает счетчики просмотров рецептов с помощью Redis.

Логика такова:
  • каждый пользователь может увеличивать представления рецептов только один раз
  • разные пользователи должны увеличивать счетчик
  • Redis имитируется с помощью MagicMock
Первый тест пройден, и часть второго теста пройдена, но счетчик никогда не увеличивается до 2 для второго пользователя, хотя я явно меняю ложные возвращаемые значения.
Django View

Код: Выделить всё

# recipehub/apps/recipes/views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render

from recipehub.apps.recipes.models import Recipe
from recipehub.redis import r

@login_required
def recipe_detail(request, slug):
recipe = get_object_or_404(Recipe, slug=slug, moderation_status="approved")

redis_user_recipe_view_key = f"user:{request.user.id}:recipe:{recipe.id}:view"
redis_all_recipe_view_key = f"recipe:{recipe.id}:views"

if not r.exists(redis_user_recipe_view_key):
r.set(redis_user_recipe_view_key, 1)
r.incr(redis_all_recipe_view_key)

recipe_views = int(r.get(redis_all_recipe_view_key) or 0)

return render(
request,
"recipes/recipe_detail.html",
{
"recipe": recipe,
"views": recipe_views,
},
)
Определение клиента Redis

Код: Выделить всё

# recipehub/redis.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
**
Имитация Redis**

Код: Выделить всё

import pytest
from unittest.mock import MagicMock

@pytest.fixture()
def mock_redis(mocker):
magic_mock = MagicMock()
mocker.patch("recipehub.redis.r", magic_mock)
return magic_mock
Тест 1 — первый пользователь увеличивает счетчик (проходит)

Код: Выделить всё

@pytest.mark.django_db
def test_recipe_detail_first_user_view_increments_counter(client, users_list, mock_redis):
recipe = RecipeFactory.create(slug="fish", moderation_status="approved")
user = users_list["first_simple_user"]

mock_redis.exists.return_value = False
mock_redis.get.return_value = b'1'
mock_redis.incr.return_value = 1
mock_redis.set.return_value = True

client.force_login(user)
response = client.get(
reverse("recipes:recipe-detail", kwargs={"slug": recipe.slug})
)

assertContains(response, '1 views')
Тест 2 — разные пользователи должны увеличивать счетчик (не пройден)

Код: Выделить всё

@pytest.mark.django_db
def test_recipe_detail_different_users_increment_counter(client, users_list, mock_redis):
recipe = RecipeFactory.create(slug="fish", moderation_status="approved")
first_user = users_list["first_simple_user"]
second_user = users_list["second_simple_user"]

# First user visit
mock_redis.exists.return_value = False
mock_redis.get.return_value = b'1'

client.force_login(first_user)
first_response = client.get(
reverse("recipes:recipe-detail", kwargs={"slug": recipe.slug})
)
assertContains(first_response, '1 views')

# Second user visit
mock_redis.exists.return_value = False
mock_redis.get.return_value = b'2'

client.force_login(second_user)
second_response = client.get(
reverse("recipes:recipe-detail", kwargs={"slug": recipe.slug})
)

# FAILS: still shows "1 views"
assertContains(second_response, '2 views')

assert mock_redis.incr.call_count == 2
assert mock_redis.set.call_count == 2
Несмотря на то, что я меняюock_redis.get.return_value на b'2' перед вторым запросом,

в ответе по-прежнему отображается «1 просмотр».
Метод incr() вызывается дважды, но значение, возвращаемое get(), не отражает этого.
Как правильно имитировать Redis в pytest-django для таких счетчиков, как incr/get? Является ли MagicMock недостаточным для этого случая?

Подробнее здесь: https://stackoverflow.com/questions/798 ... rent-users

Вернуться в «Python»