mirror of
https://github.com/jpawlowski/hass.tibber_prices.git
synced 2026-03-30 13:23:41 +00:00
Added 40+ tests verifying memory leak prevention patterns: - Listener cleanup: Time-sensitive, minute-update, lifecycle callbacks - Timer cancellation: Quarter-hour, minute timers - Config entry cleanup: Options update listener via async_on_unload - Cache invalidation: Config, period, trend caches - Storage cleanup: Cache files deleted on entry removal Tests verify cleanup patterns exist in code (not full integration tests due to complex mocking requirements). Impact: Documents and tests cleanup contracts for future maintainability. Prevents memory leaks when entities removed or config changed.
62 lines
2.1 KiB
Python
62 lines
2.1 KiB
Python
"""Test coordinator shutdown and cache persistence."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
|
|
import pytest
|
|
|
|
# Import at module level to avoid PLC0415
|
|
from custom_components.tibber_prices.coordinator.core import (
|
|
TibberPricesDataUpdateCoordinator,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_coordinator_shutdown_saves_cache() -> None:
|
|
"""
|
|
Test that coordinator saves cache during shutdown.
|
|
|
|
This ensures no data is lost when Home Assistant shuts down.
|
|
"""
|
|
# Create mock coordinator bypassing __init__
|
|
coordinator = object.__new__(TibberPricesDataUpdateCoordinator)
|
|
|
|
# Mock the _store_cache method and listener manager
|
|
coordinator._store_cache = AsyncMock() # noqa: SLF001
|
|
mock_manager = MagicMock()
|
|
mock_manager.cancel_timers = MagicMock()
|
|
coordinator._listener_manager = mock_manager # noqa: SLF001
|
|
coordinator._log = lambda *_a, **_kw: None # noqa: SLF001
|
|
|
|
# Call shutdown
|
|
await coordinator.async_shutdown()
|
|
|
|
# Verify cache was saved
|
|
coordinator._store_cache.assert_called_once() # noqa: SLF001
|
|
# Verify timers were cancelled
|
|
mock_manager.cancel_timers.assert_called_once()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_coordinator_shutdown_handles_cache_error() -> None:
|
|
"""
|
|
Test that shutdown completes even if cache save fails.
|
|
|
|
Shutdown should be resilient and not raise exceptions.
|
|
"""
|
|
# Create mock coordinator bypassing __init__
|
|
coordinator = object.__new__(TibberPricesDataUpdateCoordinator)
|
|
|
|
# Mock _store_cache to raise an exception
|
|
coordinator._store_cache = AsyncMock(side_effect=OSError("Disk full")) # noqa: SLF001
|
|
mock_manager = MagicMock()
|
|
mock_manager.cancel_timers = MagicMock()
|
|
coordinator._listener_manager = mock_manager # noqa: SLF001
|
|
coordinator._log = lambda *_a, **_kw: None # noqa: SLF001
|
|
|
|
# Shutdown should complete without raising
|
|
await coordinator.async_shutdown()
|
|
|
|
# Verify _store_cache was called (even though it raised)
|
|
coordinator._store_cache.assert_called_once() # noqa: SLF001
|
|
# Verify timers were still cancelled despite error
|
|
mock_manager.cancel_timers.assert_called_once()
|