From 7100481abc4c2cc74b3c0d46f6de05ee930bf2b6 Mon Sep 17 00:00:00 2001 From: Thomas55555 <59625598+Thomas55555@users.noreply.github.com> Date: Thu, 8 May 2025 22:38:26 +0200 Subject: [PATCH] Improve Husqvarna Automower tests (#143113) --- .../husqvarna_automower/conftest.py | 56 +++++++------------ .../husqvarna_automower/test_button.py | 6 +- .../husqvarna_automower/test_lawn_mower.py | 14 ++--- .../husqvarna_automower/test_number.py | 2 +- .../husqvarna_automower/test_switch.py | 3 +- 5 files changed, 29 insertions(+), 52 deletions(-) diff --git a/tests/components/husqvarna_automower/conftest.py b/tests/components/husqvarna_automower/conftest.py index 871f108bfd0..1cd6f9b393e 100644 --- a/tests/components/husqvarna_automower/conftest.py +++ b/tests/components/husqvarna_automower/conftest.py @@ -3,10 +3,10 @@ import asyncio from collections.abc import Generator import time -from unittest.mock import AsyncMock, patch +from unittest.mock import AsyncMock, create_autospec, patch +from aioautomower.commands import MowerCommands, WorkAreaSettings from aioautomower.model import MowerAttributes -from aioautomower.session import AutomowerSession, MowerCommands from aioautomower.utils import mower_list_to_dictionary_dataclass from aiohttp import ClientWebSocketResponse import pytest @@ -108,7 +108,9 @@ async def setup_credentials(hass: HomeAssistant) -> None: @pytest.fixture -def mock_automower_client(values) -> Generator[AsyncMock]: +def mock_automower_client( + values: dict[str, MowerAttributes], +) -> Generator[AsyncMock]: """Mock a Husqvarna Automower client.""" async def listen() -> None: @@ -117,37 +119,21 @@ def mock_automower_client(values) -> Generator[AsyncMock]: await listen_block.wait() pytest.fail("Listen was not cancelled!") - mock = AsyncMock(spec=AutomowerSession) - mock.auth = AsyncMock(side_effect=ClientWebSocketResponse) - mock.commands = AsyncMock(spec_set=MowerCommands) - mock.get_status.return_value = values - mock.start_listening = AsyncMock(side_effect=listen) - with patch( "homeassistant.components.husqvarna_automower.AutomowerSession", - return_value=mock, - ): - yield mock - - -@pytest.fixture -def mock_automower_client_one_mower(values) -> Generator[AsyncMock]: - """Mock a Husqvarna Automower client.""" - - async def listen() -> None: - """Mock listen.""" - listen_block = asyncio.Event() - await listen_block.wait() - pytest.fail("Listen was not cancelled!") - - mock = AsyncMock(spec=AutomowerSession) - mock.auth = AsyncMock(side_effect=ClientWebSocketResponse) - mock.commands = AsyncMock(spec_set=MowerCommands) - mock.get_status.return_value = values - mock.start_listening = AsyncMock(side_effect=listen) - - with patch( - "homeassistant.components.husqvarna_automower.AutomowerSession", - return_value=mock, - ): - yield mock + autospec=True, + spec_set=True, + ) as mock: + mock_instance = mock.return_value + mock_instance.auth = AsyncMock(side_effect=ClientWebSocketResponse) + mock_instance.get_status = AsyncMock(return_value=values) + mock_instance.start_listening = AsyncMock(side_effect=listen) + mock_instance.commands = create_autospec( + MowerCommands, instance=True, spec_set=True + ) + mock_instance.commands.workarea_settings.return_value = create_autospec( + WorkAreaSettings, + instance=True, + spec_set=True, + ) + yield mock_instance diff --git a/tests/components/husqvarna_automower/test_button.py b/tests/components/husqvarna_automower/test_button.py index 5bef810150d..b76bc7c9d73 100644 --- a/tests/components/husqvarna_automower/test_button.py +++ b/tests/components/husqvarna_automower/test_button.py @@ -64,8 +64,7 @@ async def test_button_states_and_commands( target={ATTR_ENTITY_ID: entity_id}, blocking=True, ) - mocked_method = getattr(mock_automower_client.commands, "error_confirm") - mocked_method.assert_called_once_with(TEST_MOWER_ID) + mock_automower_client.commands.error_confirm.assert_called_once_with(TEST_MOWER_ID) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == "2023-06-05T00:16:00+00:00" @@ -106,8 +105,7 @@ async def test_sync_clock( {ATTR_ENTITY_ID: entity_id}, blocking=True, ) - mocked_method = mock_automower_client.commands.set_datetime - mocked_method.assert_called_once_with(TEST_MOWER_ID) + mock_automower_client.commands.set_datetime.assert_called_once_with(TEST_MOWER_ID) await hass.async_block_till_done() state = hass.states.get(entity_id) assert state.state == "2024-02-29T11:00:00+00:00" diff --git a/tests/components/husqvarna_automower/test_lawn_mower.py b/tests/components/husqvarna_automower/test_lawn_mower.py index 12c53d709ca..42b737652b7 100644 --- a/tests/components/husqvarna_automower/test_lawn_mower.py +++ b/tests/components/husqvarna_automower/test_lawn_mower.py @@ -90,9 +90,7 @@ async def test_lawn_mower_commands( mocked_method = getattr(mock_automower_client.commands, aioautomower_command) mocked_method.assert_called_once_with(TEST_MOWER_ID) - getattr( - mock_automower_client.commands, aioautomower_command - ).side_effect = ApiError("Test error") + mocked_method.side_effect = ApiError("Test error") with pytest.raises( HomeAssistantError, match="Failed to send command: Test error", @@ -139,8 +137,7 @@ async def test_lawn_mower_service_commands( ) -> None: """Test lawn_mower commands.""" await setup_integration(hass, mock_config_entry) - mocked_method = AsyncMock() - setattr(mock_automower_client.commands, aioautomower_command, mocked_method) + mocked_method = getattr(mock_automower_client.commands, aioautomower_command) await hass.services.async_call( domain=DOMAIN, service=service, @@ -150,9 +147,7 @@ async def test_lawn_mower_service_commands( ) mocked_method.assert_called_once_with(TEST_MOWER_ID, extra_data) - getattr( - mock_automower_client.commands, aioautomower_command - ).side_effect = ApiError("Test error") + mocked_method.side_effect = ApiError("Test error") with pytest.raises( HomeAssistantError, match="Failed to send command: Test error", @@ -193,8 +188,7 @@ async def test_lawn_mower_override_work_area_command( ) -> None: """Test lawn_mower work area override commands.""" await setup_integration(hass, mock_config_entry) - mocked_method = AsyncMock() - setattr(mock_automower_client.commands, aioautomower_command, mocked_method) + mocked_method = getattr(mock_automower_client.commands, aioautomower_command) await hass.services.async_call( domain=DOMAIN, service=service, diff --git a/tests/components/husqvarna_automower/test_number.py b/tests/components/husqvarna_automower/test_number.py index 628011e3f15..005d294954c 100644 --- a/tests/components/husqvarna_automower/test_number.py +++ b/tests/components/husqvarna_automower/test_number.py @@ -96,7 +96,7 @@ async def test_number_workarea_commands( service_data={"value": "75"}, blocking=True, ) - assert len(mocked_method.mock_calls) == 2 + assert mock_automower_client.commands.workarea_settings.call_count == 2 @pytest.mark.usefixtures("entity_registry_enabled_by_default") diff --git a/tests/components/husqvarna_automower/test_switch.py b/tests/components/husqvarna_automower/test_switch.py index 00b04ce9903..06efb8c45c0 100644 --- a/tests/components/husqvarna_automower/test_switch.py +++ b/tests/components/husqvarna_automower/test_switch.py @@ -133,8 +133,7 @@ async def test_stay_out_zone_switch_commands( ) values[TEST_MOWER_ID].stay_out_zones.zones[TEST_ZONE_ID].enabled = boolean mock_automower_client.get_status.return_value = values - mocked_method = AsyncMock() - setattr(mock_automower_client.commands, "switch_stay_out_zone", mocked_method) + mocked_method = mock_automower_client.commands.switch_stay_out_zone await hass.services.async_call( domain=SWITCH_DOMAIN, service=service,