mirror of
https://github.com/OMGeeky/homecontrol.esp-sensors.git
synced 2025-12-31 00:21:46 +01:00
161 lines
5.2 KiB
Python
161 lines
5.2 KiB
Python
"""
|
|
Tests for the MQTT module.
|
|
"""
|
|
|
|
import pytest
|
|
import json
|
|
from unittest.mock import patch, MagicMock
|
|
from src.esp_sensors.mqtt import setup_mqtt, publish_sensor_data, MQTTClient
|
|
|
|
|
|
class TestSensor:
|
|
"""Mock sensor class for testing."""
|
|
|
|
__test__ = False # Prevent pytest from treating this as a test case
|
|
|
|
def __init__(self, name="Test Sensor", temperature_unit="C"):
|
|
self.name = name
|
|
self.temperature_unit = temperature_unit
|
|
|
|
|
|
@pytest.fixture
|
|
def mqtt_config():
|
|
"""Fixture providing a sample MQTT configuration."""
|
|
return {
|
|
"enabled": True,
|
|
"broker": "test.mosquitto.org",
|
|
"port": 1883,
|
|
"client_id": "test_client",
|
|
"username": "test_user",
|
|
"password": "test_pass",
|
|
"topic_prefix": "test/sensors",
|
|
"publish_interval": 30,
|
|
"ssl": False,
|
|
"keepalive": 60,
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def disabled_mqtt_config():
|
|
"""Fixture providing a disabled MQTT configuration."""
|
|
return {
|
|
"enabled": False,
|
|
"broker": "test.mosquitto.org",
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_sensor():
|
|
"""Fixture providing a mock sensor."""
|
|
return TestSensor(name="DHT22 Sensor", temperature_unit="C")
|
|
|
|
|
|
def test_setup_mqtt_disabled(disabled_mqtt_config):
|
|
"""Test that setup_mqtt returns None when MQTT is disabled."""
|
|
client = setup_mqtt(disabled_mqtt_config)
|
|
assert client is None
|
|
|
|
|
|
def test_setup_mqtt_enabled(mqtt_config):
|
|
"""Test that setup_mqtt creates and connects a client when MQTT is enabled."""
|
|
with patch("src.esp_sensors.mqtt.MQTTClient") as mock_mqtt_client:
|
|
# Configure the mock
|
|
mock_client_instance = MagicMock()
|
|
mock_mqtt_client.return_value = mock_client_instance
|
|
|
|
# Call the function
|
|
client = setup_mqtt(mqtt_config)
|
|
|
|
# Verify MQTTClient was created with correct parameters
|
|
mock_mqtt_client.assert_called_once_with(
|
|
mqtt_config["client_id"],
|
|
mqtt_config["broker"],
|
|
mqtt_config["port"],
|
|
mqtt_config["username"],
|
|
mqtt_config["password"],
|
|
mqtt_config["keepalive"],
|
|
mqtt_config["ssl"],
|
|
)
|
|
|
|
# Verify connect was called
|
|
mock_client_instance.connect.assert_called_once()
|
|
|
|
# Verify the client was returned
|
|
assert client == mock_client_instance
|
|
|
|
|
|
def test_setup_mqtt_connection_error(mqtt_config):
|
|
"""Test that setup_mqtt handles connection errors gracefully."""
|
|
with patch("src.esp_sensors.mqtt.MQTTClient") as mock_mqtt_client:
|
|
# Configure the mock to raise an exception on connect
|
|
mock_client_instance = MagicMock()
|
|
mock_client_instance.connect.side_effect = Exception("Connection failed")
|
|
mock_mqtt_client.return_value = mock_client_instance
|
|
|
|
# Call the function
|
|
client = setup_mqtt(mqtt_config)
|
|
|
|
# Verify connect was called
|
|
mock_client_instance.connect.assert_called_once()
|
|
|
|
# Verify None was returned due to the error
|
|
assert client is None
|
|
|
|
|
|
def test_publish_sensor_data_success(mqtt_config, mock_sensor):
|
|
"""Test that publish_sensor_data publishes to the correct topics."""
|
|
# Create a mock client
|
|
mock_client = MagicMock()
|
|
|
|
# Call the function
|
|
temperature = 25.5
|
|
humidity = 60.0
|
|
result = publish_sensor_data(
|
|
mock_client, mqtt_config, mock_sensor, temperature, humidity
|
|
)
|
|
|
|
# Verify the result
|
|
assert result is True
|
|
|
|
# Verify publish was called for temperature
|
|
temp_topic = f"{mqtt_config['topic_prefix']}/{mock_sensor.name.lower().replace(' ', '_')}/temperature"
|
|
mock_client.publish.assert_any_call(temp_topic, str(temperature).encode())
|
|
|
|
# Verify publish was called for humidity
|
|
humidity_topic = f"{mqtt_config['topic_prefix']}/{mock_sensor.name.lower().replace(' ', '_')}/humidity"
|
|
mock_client.publish.assert_any_call(humidity_topic, str(humidity).encode())
|
|
|
|
# Verify publish was called for combined data
|
|
data_topic = f"{mqtt_config['topic_prefix']}/{mock_sensor.name.lower().replace(' ', '_')}/data"
|
|
# Check that the JSON data was published
|
|
for call_args in mock_client.publish.call_args_list:
|
|
if call_args[0][0] == data_topic:
|
|
# Parse the JSON data
|
|
data = json.loads(call_args[0][1].decode())
|
|
assert data["temperature"] == temperature
|
|
assert data["humidity"] == humidity
|
|
assert data["unit"] == mock_sensor.temperature_unit
|
|
assert "timestamp" in data
|
|
break
|
|
else:
|
|
pytest.fail("Data topic was not published")
|
|
|
|
|
|
def test_publish_sensor_data_no_client(mqtt_config, mock_sensor):
|
|
"""Test that publish_sensor_data returns False when client is None."""
|
|
result = publish_sensor_data(None, mqtt_config, mock_sensor, 25.5, 60.0)
|
|
assert result is False
|
|
|
|
|
|
def test_publish_sensor_data_error(mqtt_config, mock_sensor):
|
|
"""Test that publish_sensor_data handles errors gracefully."""
|
|
# Create a mock client that raises an exception on publish
|
|
mock_client = MagicMock()
|
|
mock_client.publish.side_effect = Exception("Publish failed")
|
|
|
|
# Call the function
|
|
result = publish_sensor_data(mock_client, mqtt_config, mock_sensor, 25.5, 60.0)
|
|
|
|
# Verify the result
|
|
assert result is False
|