Der Zähler für verspottete Redis erhöht sich nicht zwischen Anfragen für verschiedene BenutzerPython

Python-Programme
Anonymous
 Der Zähler für verspottete Redis erhöht sich nicht zwischen Anfragen für verschiedene Benutzer

Post by Anonymous »

Ich teste eine Django-Ansicht, die Rezeptansichtszähler mithilfe von Redis erhöht.

Die Logik lautet:
  • Jeder Benutzer kann Rezeptansichten nur einmal erhöhen
  • verschiedene Benutzer sollten den Zähler erhöhen
  • Redis wird mit MagicMock verspottet
Der erste Test besteht und ein Teil des zweiten Tests besteht, aber der Zähler wird für den zweiten Benutzer nie auf 2 erhöht, auch wenn ich die Scheinrückgabewerte explizit ändere.
Django View

Code: Select all

# 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-Client-Definition

Code: Select all

# recipehub/redis.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
**
Redis-Mock-Fixture**

Code: Select all

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
Test 1 – erster Benutzer erhöht den Zähler (bestanden)

Code: Select all

@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')
Test 2 – verschiedene Benutzer sollten den Zähler erhöhen (schlägt fehl)

Code: Select all

@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
Auch wenn ich „mock_redis.get.return_value“ vor der zweiten Anfrage in „b'2“ ändere,

zeigt die Antwort immer noch „1 Ansichten“.
Die incr()-Methode wird zweimal aufgerufen, aber der von get() zurückgegebene Wert spiegelt dies nicht wider.
Was ist der richtige Weg, um Redis zu verspotten? pytest-django für Zähler wie incr/get? Reicht MagicMock für diesen Fall nicht aus?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post