Files
core/tests/test_cache_logic_only.py
Untone f891b73608
All checks were successful
Deploy on push / deploy (push) Successful in 5m46s
following-debug
2025-08-30 18:23:15 +03:00

175 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Простой тест кеша подписок без GraphQL и авторизации
"""
from __future__ import annotations
import asyncio
import time
import pytest
from cache.cache import get_cached_follower_authors
from orm.author import Author, AuthorFollower
from storage.db import local_session
from storage.redis import redis
@pytest.mark.asyncio
async def test_cache_invalidation_logic():
"""
Тест логики инвалидации кеша при прямых операциях с БД
"""
# Создаем тестовых пользователей
with local_session() as session:
follower = Author(
name="Cache Test Follower",
slug=f"cache-test-follower-{int(time.time())}",
email=f"cache-follower-{int(time.time())}@test.com"
)
session.add(follower)
target_author = Author(
name="Cache Test Target",
slug=f"cache-test-target-{int(time.time())}",
email=f"cache-target-{int(time.time())}@test.com"
)
session.add(target_author)
session.commit()
follower_id = follower.id
target_author_id = target_author.id
try:
# 1. Очищаем кеш
cache_key = f"author:follows-authors:{follower_id}"
await redis.execute("DEL", cache_key)
# 2. Проверяем начальное состояние (пустой список)
initial_follows = await get_cached_follower_authors(follower_id)
assert len(initial_follows) == 0, "Изначально подписок быть не должно"
# 3. Создаем подписку в БД напрямую
with local_session() as session:
subscription = AuthorFollower(
follower=follower_id,
following=target_author_id
)
session.add(subscription)
session.commit()
# 4. Инвалидируем кеш (имитируя логику follow)
await redis.execute("DEL", cache_key)
# 5. Проверяем, что кеш обновился
after_follow_follows = await get_cached_follower_authors(follower_id)
assert len(after_follow_follows) == 1, "После подписки должна быть 1 запись"
assert after_follow_follows[0]["id"] == target_author_id, "ID должен совпадать"
# 6. Проверяем, что второй запрос берется из кеша
cached_follows = await get_cached_follower_authors(follower_id)
assert len(cached_follows) == 1, "Кеш должен содержать 1 запись"
assert cached_follows[0]["id"] == target_author_id, "ID в кеше должен совпадать"
# 7. Удаляем подписку из БД
with local_session() as session:
session.query(AuthorFollower).filter(
AuthorFollower.follower == follower_id,
AuthorFollower.following == target_author_id
).delete()
session.commit()
# 8. Инвалидируем кеш (имитируя логику unfollow)
await redis.execute("DEL", cache_key)
# 9. Проверяем, что кеш снова пустой
after_unfollow_follows = await get_cached_follower_authors(follower_id)
assert len(after_unfollow_follows) == 0, "После отписки кеш должен быть пустым"
print("✅ Тест логики кеширования прошел успешно!")
finally:
# Очистка
with local_session() as session:
session.query(AuthorFollower).filter(
AuthorFollower.follower == follower_id
).delete()
session.query(Author).filter(Author.id.in_([follower_id, target_author_id])).delete()
session.commit()
await redis.execute("DEL", cache_key)
@pytest.mark.asyncio
async def test_cache_miss_behavior():
"""
Тест поведения при промахе кеша - данные должны браться из БД
"""
with local_session() as session:
follower = Author(
name="Cache Miss Test",
slug=f"cache-miss-{int(time.time())}",
email=f"cache-miss-{int(time.time())}@test.com"
)
session.add(follower)
target1 = Author(
name="Target 1",
slug=f"target-1-{int(time.time())}",
email=f"target-1-{int(time.time())}@test.com"
)
session.add(target1)
target2 = Author(
name="Target 2",
slug=f"target-2-{int(time.time())}",
email=f"target-2-{int(time.time())}@test.com"
)
session.add(target2)
session.commit()
follower_id = follower.id
target1_id = target1.id
target2_id = target2.id
# Создаем подписки в БД
sub1 = AuthorFollower(follower=follower_id, following=target1_id)
sub2 = AuthorFollower(follower=follower_id, following=target2_id)
session.add_all([sub1, sub2])
session.commit()
try:
cache_key = f"author:follows-authors:{follower_id}"
# Убеждаемся, что кеша нет
await redis.execute("DEL", cache_key)
# Запрашиваем данные (должно произойти cache miss и загрузка из БД)
follows = await get_cached_follower_authors(follower_id)
assert len(follows) == 2, "Должно быть 2 подписки"
follow_ids = {f["id"] for f in follows}
assert target1_id in follow_ids, "Должна быть подписка на target1"
assert target2_id in follow_ids, "Должна быть подписка на target2"
# Второй запрос должен брать из кеша
cached_follows = await get_cached_follower_authors(follower_id)
assert len(cached_follows) == 2, "Кеш должен содержать 2 записи"
print("✅ Тест cache miss поведения прошел успешно!")
finally:
# Очистка
with local_session() as session:
session.query(AuthorFollower).filter(
AuthorFollower.follower == follower_id
).delete()
session.query(Author).filter(Author.id.in_([follower_id, target1_id, target2_id])).delete()
session.commit()
await redis.execute("DEL", cache_key)
if __name__ == "__main__":
asyncio.run(test_cache_invalidation_logic())
asyncio.run(test_cache_miss_behavior())
print("🎯 Все тесты кеша прошли успешно!")