|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
| 3 | +from collections.abc import Iterator |
3 | 4 | from dataclasses import fields |
4 | 5 | from typing import Callable |
5 | 6 |
|
6 | 7 | import pytest |
| 8 | +from loguru import logger |
7 | 9 | from typer.testing import CliRunner |
8 | 10 |
|
9 | 11 | from pms.main import main |
|
12 | 14 |
|
13 | 15 |
|
14 | 16 | @pytest.fixture() |
15 | | -def mock_mqtt_publisher(monkeypatch: pytest.MonkeyPatch): |
16 | | - """mock pms.extra.mqtt.publisher""" |
17 | | - from pms.extra.mqtt import Publisher |
| 17 | +def mock_mqtt_client(captured_data, monkeypatch: pytest.MonkeyPatch): |
| 18 | + from pms.extra.mqtt import Data |
| 19 | + |
| 20 | + def mqtt_messages() -> Iterator[Data]: |
| 21 | + for obs in captured_data.obs: |
| 22 | + for field in fields(obs): |
| 23 | + if not field.metadata: |
| 24 | + continue |
| 25 | + yield Data(obs.time, "test", field.name, getattr(obs, field.name)) |
| 26 | + |
| 27 | + class MockClient: |
| 28 | + _message = mqtt_messages() |
| 29 | + |
| 30 | + def __init__(self, *, client_id: str): |
| 31 | + assert client_id in {"homie/test", "homie/+/+/+"} |
18 | 32 |
|
19 | | - def publisher(*, topic: str, host: str, port: int, username: str, password: str) -> Publisher: |
20 | | - def pub(data: dict[str, int | str]) -> None: |
| 33 | + def enable_logger(self, logger): # noqa: F811 |
21 | 34 | pass |
22 | 35 |
|
23 | | - return pub |
| 36 | + def username_pw_set(self, username: str | None, password: str | None = None): |
| 37 | + assert username is None |
| 38 | + assert password is None |
| 39 | + |
| 40 | + def will_set(self, topic, payload=None, qos=0, retain=False, properties=None): |
| 41 | + assert topic.endswith("$online") |
| 42 | + assert payload == "false" |
| 43 | + assert qos == 1 |
| 44 | + assert retain is True |
| 45 | + |
| 46 | + def connect(self, host, port=1883): |
| 47 | + assert host == "test.mosquitto.org" |
| 48 | + assert port == 1883 # MQTT, unencrypted, unauthenticated |
| 49 | + |
| 50 | + def publish(self, topic, payload=None, qos=0, retain=False, properties=None): |
| 51 | + logger.debug(f"{topic} = {payload}") |
| 52 | + assert topic.startswith("homie/test/") |
| 53 | + assert isinstance(payload, (str, float, int)) |
| 54 | + assert qos == 1 |
| 55 | + assert retain is True |
| 56 | + if isinstance(payload, (float, int)): |
| 57 | + logger.debug(msg := next(self._message)) |
| 58 | + assert Data.decode(topic, payload, time=msg.time) == msg |
| 59 | + |
| 60 | + def _handle_on_message(self, message): |
| 61 | + logger.debug("_handle_on_message") |
| 62 | + assert self.on_message is not None |
| 63 | + |
| 64 | + def loop_start(self): |
| 65 | + logger.debug("loop_start") |
| 66 | + |
| 67 | + def loop_forever(self, timeout=1, retry_first_connection=False): |
| 68 | + logger.debug("loop_forever") |
24 | 69 |
|
25 | | - monkeypatch.setattr("pms.extra.mqtt.publisher", publisher) |
| 70 | + monkeypatch.setattr("pms.extra.mqtt.Client", MockClient) |
26 | 71 |
|
27 | 72 |
|
28 | 73 | @pytest.fixture() |
29 | | -def mock_mqtt_subscribe(captured_data, monkeypatch: pytest.MonkeyPatch, replay_time): |
| 74 | +def mock_mqtt_subscribe(captured_data, monkeypatch: pytest.MonkeyPatch): |
30 | 75 | """mock ms.extra.mqtt.subscribe""" |
31 | 76 | from pms.extra.mqtt import Data |
32 | 77 |
|
@@ -60,16 +105,16 @@ def publisher(*, host: str, port: int, username: str, password: str, db_name: st |
60 | 105 | def pub(*, time: int, tags: dict[str, str], data: dict[str, float]) -> None: |
61 | 106 | tag = ",".join(f"{k},{v}" for k, v in tags.items()) |
62 | 107 | for key, val in data.items(): |
63 | | - print(f"{time},{tag},{key},{val}") |
| 108 | + logger.debug(f"{time},{tag},{key},{val}") |
64 | 109 |
|
65 | 110 | return pub |
66 | 111 |
|
67 | 112 | monkeypatch.setattr("pms.extra.influxdb.publisher", publisher) |
68 | 113 |
|
69 | 114 |
|
70 | | -@pytest.mark.usefixtures("mock_mqtt_publisher") |
| 115 | +@pytest.mark.usefixtures("mock_mqtt_client") |
71 | 116 | def test_mqtt(capture): |
72 | | - result = runner.invoke(main, capture.options("mqtt")) |
| 117 | + result = runner.invoke(main, capture.options("mqtt", debug=True)) |
73 | 118 | assert result.exit_code == 0 |
74 | 119 |
|
75 | 120 |
|
|
0 commit comments