Files
mostovik-backend/tests/apps/core/test_cache.py
Aleksandr Meshchriakov f121445313 feat(core): add core module with mixins, services, and background jobs
- Add Model Mixins: TimestampMixin, SoftDeleteMixin, AuditMixin, etc.
- Add Base Services: BaseService, BulkOperationsMixin, QueryOptimizerMixin
- Add Base ViewSets with bulk operations
- Add BackgroundJob model for Celery task tracking
- Add BaseAppCommand for management commands
- Add permissions, pagination, filters, cache, logging
- Migrate tests to factory_boy + faker
- Add CHANGELOG.md
- 297 tests passing
2026-01-21 11:47:26 +01:00

194 lines
5.8 KiB
Python

"""Tests for core cache utilities"""
from apps.core.cache import (
CacheManager,
_build_cache_key,
cache_method,
cache_result,
)
from django.core.cache import cache
from django.test import TestCase
class CacheResultDecoratorTest(TestCase):
"""Tests for @cache_result decorator"""
def setUp(self):
cache.clear()
self.call_count = 0
def test_result_is_cached(self):
"""Test that function result is cached"""
@cache_result(timeout=60, key_prefix="test")
def expensive_function(x):
self.call_count += 1
return x * 2
# First call - should execute
result1 = expensive_function(5)
self.assertEqual(result1, 10)
self.assertEqual(self.call_count, 1)
# Second call - should return cached result
result2 = expensive_function(5)
self.assertEqual(result2, 10)
self.assertEqual(self.call_count, 1) # Still 1, not called again
def test_different_args_not_cached(self):
"""Test that different arguments create different cache entries"""
@cache_result(timeout=60, key_prefix="test")
def expensive_function(x):
self.call_count += 1
return x * 2
result1 = expensive_function(5)
result2 = expensive_function(10)
self.assertEqual(result1, 10)
self.assertEqual(result2, 20)
self.assertEqual(self.call_count, 2)
def test_kwargs_included_in_cache_key(self):
"""Test that kwargs are included in cache key"""
@cache_result(timeout=60, key_prefix="test")
def expensive_function(x, multiplier=2):
self.call_count += 1
return x * multiplier
result1 = expensive_function(5, multiplier=2)
result2 = expensive_function(5, multiplier=3)
self.assertEqual(result1, 10)
self.assertEqual(result2, 15)
self.assertEqual(self.call_count, 2)
class CacheMethodDecoratorTest(TestCase):
"""Tests for @cache_method decorator"""
def setUp(self):
cache.clear()
def test_classmethod_caching(self):
"""Test caching works with classmethod"""
call_count = {"value": 0}
class MyService:
@classmethod
@cache_method(timeout=60, key_prefix="service")
def get_data(cls, item_id):
call_count["value"] += 1
return {"id": item_id, "data": "test"}
# First call
result1 = MyService.get_data(1)
self.assertEqual(result1["id"], 1)
self.assertEqual(call_count["value"], 1)
# Second call - should be cached
result2 = MyService.get_data(1)
self.assertEqual(result2["id"], 1)
self.assertEqual(call_count["value"], 1)
# Different argument
result3 = MyService.get_data(2)
self.assertEqual(result3["id"], 2)
self.assertEqual(call_count["value"], 2)
class CacheManagerTest(TestCase):
"""Tests for CacheManager"""
def setUp(self):
cache.clear()
self.manager = CacheManager("test_prefix")
def test_set_and_get(self):
"""Test basic set and get operations"""
self.manager.set("key1", "value1", timeout=60)
result = self.manager.get("key1")
self.assertEqual(result, "value1")
def test_get_default(self):
"""Test get returns default for missing key"""
result = self.manager.get("nonexistent", default="default_value")
self.assertEqual(result, "default_value")
def test_delete(self):
"""Test delete operation"""
self.manager.set("key1", "value1")
self.manager.delete("key1")
result = self.manager.get("key1")
self.assertIsNone(result)
def test_get_or_set(self):
"""Test get_or_set operation"""
call_count = {"value": 0}
def compute_value():
call_count["value"] += 1
return "computed"
# First call - should compute
result1 = self.manager.get_or_set("key1", compute_value)
self.assertEqual(result1, "computed")
self.assertEqual(call_count["value"], 1)
# Second call - should return cached
result2 = self.manager.get_or_set("key1", compute_value)
self.assertEqual(result2, "computed")
self.assertEqual(call_count["value"], 1)
def test_prefix_applied(self):
"""Test that prefix is applied to keys"""
self.manager.set("mykey", "myvalue")
# Direct cache access should use prefixed key
direct_result = cache.get("test_prefix:mykey")
self.assertEqual(direct_result, "myvalue")
class BuildCacheKeyTest(TestCase):
"""Tests for _build_cache_key function"""
def test_key_includes_function_name(self):
"""Test cache key includes function name"""
def my_function():
pass
key = _build_cache_key(my_function, "", (), {})
self.assertIn("my_function", key)
def test_key_includes_prefix(self):
"""Test cache key includes prefix"""
def my_function():
pass
key = _build_cache_key(my_function, "myprefix", (), {})
self.assertTrue(key.startswith("myprefix:"))
def test_different_args_different_keys(self):
"""Test different arguments produce different keys"""
def my_function():
pass
key1 = _build_cache_key(my_function, "", (1, 2), {})
key2 = _build_cache_key(my_function, "", (1, 3), {})
self.assertNotEqual(key1, key2)
def test_different_kwargs_different_keys(self):
"""Test different kwargs produce different keys"""
def my_function():
pass
key1 = _build_cache_key(my_function, "", (), {"a": 1})
key2 = _build_cache_key(my_function, "", (), {"a": 2})
self.assertNotEqual(key1, key2)