Files
demeter/server/tests/conftest.py

99 lines
2.9 KiB
Python

"""
Shared fixtures for Demeter server tests.
"""
from __future__ import annotations
import asyncio
from typing import Any
from unittest.mock import AsyncMock, MagicMock
import pytest
from fastapi.testclient import TestClient
from app.config import DeviceConfig, DevicesConfig, ResourceConfig, Settings
from app.device_store import DeviceStore
from app.metrics import MetricsCollector
@pytest.fixture
def sample_devices_config() -> DevicesConfig:
"""A minimal device config for testing."""
return DevicesConfig(
devices=[
DeviceConfig(
id="test-plant-01",
name="Test Plant",
ip="192.168.1.100",
port=5683,
enabled=True,
resources=[
ResourceConfig(uri="sensors/soil_moisture", name="Soil Moisture", type="periodic"),
ResourceConfig(uri="sensors/temperature", name="Temperature", type="periodic"),
ResourceConfig(uri="events/trigger", name="Trigger", type="event"),
],
),
DeviceConfig(
id="test-aquarium-01",
name="Test Aquarium",
ip="192.168.1.101",
port=5683,
enabled=True,
resources=[
ResourceConfig(uri="sensors/temperature", name="Water Temp", type="periodic"),
],
),
DeviceConfig(
id="test-disabled",
name="Disabled Device",
ip="192.168.1.102",
port=5683,
enabled=False,
resources=[],
),
]
)
@pytest.fixture
def store(sample_devices_config: DevicesConfig) -> DeviceStore:
"""An initialized DeviceStore with sample devices."""
return DeviceStore(sample_devices_config)
@pytest.fixture
def mock_observer() -> MagicMock:
"""A mock CoapObserverClient for API tests."""
observer = MagicMock()
observer.active_subscriptions = 3
observer.subscription_status.return_value = {
"test-plant-01/sensors/soil_moisture": "running",
"test-plant-01/sensors/temperature": "running",
"test-aquarium-01/sensors/temperature": "running",
}
observer.coap_get = AsyncMock(return_value={
"device": "test-plant-01",
"temperature": 24.5,
"unit": "celsius",
})
observer.coap_put = AsyncMock(return_value={"interval": 10})
return observer
@pytest.fixture
def app(store: DeviceStore, mock_observer: MagicMock):
"""FastAPI app with mocked dependencies."""
from app.main import create_app
test_app = create_app()
test_app.state.store = store
test_app.state.observer = mock_observer
test_app.state.settings = Settings()
return test_app
@pytest.fixture
def client(app) -> TestClient:
"""FastAPI TestClient (no lifespan — dependencies are mocked)."""
return TestClient(app, raise_server_exceptions=False)