From 76f392476be4db41f787712310602575a7191f8a Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 30 Apr 2020 16:31:00 -0700 Subject: [PATCH] Use a future for mock coro (#34989) --- tests/common.py | 62 ++----------------- tests/components/alexa/test_smart_home.py | 6 +- tests/components/almond/test_init.py | 14 ++--- .../components/asuswrt/test_device_tracker.py | 23 +++---- tests/components/cast/test_init.py | 15 +++-- tests/components/cloud/__init__.py | 5 +- tests/components/cloud/test_alexa_config.py | 2 +- tests/components/cloud/test_client.py | 9 +-- tests/components/cloud/test_init.py | 29 ++++----- .../components/config/test_config_entries.py | 23 ++++--- tests/components/darksky/test_sensor.py | 11 ++-- .../components/emulated_roku/test_binding.py | 4 +- tests/components/emulated_roku/test_init.py | 10 +-- tests/components/folder_watcher/test_init.py | 36 +++++------ tests/components/http/test_view.py | 8 +-- tests/components/iqvia/test_config_flow.py | 17 ++--- tests/components/melissa/test_climate.py | 15 ++--- tests/components/melissa/test_init.py | 15 +++-- tests/components/mqtt/test_config_flow.py | 6 +- tests/components/reddit/test_sensor.py | 12 ++-- .../components/seventeentrack/test_sensor.py | 11 +--- tests/components/tplink/test_init.py | 14 ++--- tests/components/twilio/test_init.py | 41 ++++++------ tests/components/updater/test_init.py | 9 +-- tests/components/wake_on_lan/test_init.py | 7 +-- .../test_yandex_transport_sensor.py | 12 ++-- 26 files changed, 154 insertions(+), 262 deletions(-) diff --git a/tests/common.py b/tests/common.py index b76fa23bbf2..d6ae25adb5e 100644 --- a/tests/common.py +++ b/tests/common.py @@ -744,16 +744,12 @@ def patch_yaml_files(files_dict, endswith=True): def mock_coro(return_value=None, exception=None): """Return a coro that returns a value or raise an exception.""" - return mock_coro_func(return_value, exception)() - - -def mock_coro_func(return_value=None, exception=None): - """Return a method to create a coro function that returns a value.""" - - if exception: - return AsyncMock(side_effect=exception) - - return AsyncMock(return_value=return_value) + fut = asyncio.Future() + if exception is not None: + fut.set_exception(exception) + else: + fut.set_result(return_value) + return fut @contextmanager @@ -838,52 +834,6 @@ def mock_restore_cache(hass, states): hass.data[key] = hass.async_create_task(get_restore_state_data()) -class MockDependency: - """Decorator to mock install a dependency.""" - - def __init__(self, root, *args): - """Initialize decorator.""" - self.root = root - self.submodules = args - - def __enter__(self): - """Start mocking.""" - - def resolve(mock, path): - """Resolve a mock.""" - if not path: - return mock - - return resolve(getattr(mock, path[0]), path[1:]) - - base = MagicMock() - to_mock = { - f"{self.root}.{tom}": resolve(base, tom.split(".")) - for tom in self.submodules - } - to_mock[self.root] = base - - self.patcher = patch.dict("sys.modules", to_mock) - self.patcher.start() - return base - - def __exit__(self, *exc): - """Stop mocking.""" - self.patcher.stop() - return False - - def __call__(self, func): - """Apply decorator.""" - - def run_mocked(*args, **kwargs): - """Run with mocked dependencies.""" - with self as base: - args = list(args) + [base] - func(*args, **kwargs) - - return run_mocked - - class MockEntity(entity.Entity): """Mock Entity class.""" diff --git a/tests/components/alexa/test_smart_home.py b/tests/components/alexa/test_smart_home.py index 1bef3a5ae12..91864027873 100644 --- a/tests/components/alexa/test_smart_home.py +++ b/tests/components/alexa/test_smart_home.py @@ -1,5 +1,4 @@ """Test for smart home alexa support.""" -from unittest.mock import patch import pytest @@ -39,7 +38,8 @@ from . import ( reported_properties, ) -from tests.common import async_mock_service, mock_coro +from tests.async_mock import patch +from tests.common import async_mock_service @pytest.fixture @@ -3831,7 +3831,7 @@ async def test_initialize_camera_stream(hass, mock_camera, mock_stream): with patch( "homeassistant.components.demo.camera.DemoCamera.stream_source", - return_value=mock_coro("rtsp://example.local"), + return_value="rtsp://example.local", ), patch( "homeassistant.helpers.network.async_get_external_url", return_value="https://mycamerastream.test", diff --git a/tests/components/almond/test_init.py b/tests/components/almond/test_init.py index d5b8deefd5e..56286b9186c 100644 --- a/tests/components/almond/test_init.py +++ b/tests/components/almond/test_init.py @@ -1,6 +1,5 @@ """Tests for Almond set up.""" from time import time -from unittest.mock import patch import pytest @@ -10,7 +9,8 @@ from homeassistant.const import EVENT_HOMEASSISTANT_START from homeassistant.setup import async_setup_component from homeassistant.util.dt import utcnow -from tests.common import MockConfigEntry, async_fire_time_changed, mock_coro +from tests.async_mock import patch +from tests.common import MockConfigEntry, async_fire_time_changed @pytest.fixture(autouse=True) @@ -34,7 +34,6 @@ async def test_set_up_oauth_remote_url(hass, aioclient_mock): with patch( "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", - return_value=mock_coro(), ): assert await async_setup_component(hass, "almond", {}) @@ -43,9 +42,7 @@ async def test_set_up_oauth_remote_url(hass, aioclient_mock): with patch("homeassistant.components.almond.ALMOND_SETUP_DELAY", 0), patch( "homeassistant.helpers.network.async_get_external_url", return_value="https://example.nabu.casa", - ), patch( - "pyalmond.WebAlmondAPI.async_create_device", return_value=mock_coro() - ) as mock_create_device: + ), patch("pyalmond.WebAlmondAPI.async_create_device") as mock_create_device: hass.bus.async_fire(EVENT_HOMEASSISTANT_START) await hass.async_block_till_done() async_fire_time_changed(hass, utcnow()) @@ -69,7 +66,6 @@ async def test_set_up_oauth_no_external_url(hass, aioclient_mock): with patch( "homeassistant.helpers.config_entry_oauth2_flow.async_get_config_entry_implementation", - return_value=mock_coro(), ), patch("pyalmond.WebAlmondAPI.async_create_device") as mock_create_device: assert await async_setup_component(hass, "almond", {}) @@ -104,9 +100,7 @@ async def test_set_up_local(hass, aioclient_mock): ) entry.add_to_hass(hass) - with patch( - "pyalmond.WebAlmondAPI.async_create_device", return_value=mock_coro() - ) as mock_create_device: + with patch("pyalmond.WebAlmondAPI.async_create_device") as mock_create_device: assert await async_setup_component(hass, "almond", {}) assert entry.state == config_entries.ENTRY_STATE_LOADED diff --git a/tests/components/asuswrt/test_device_tracker.py b/tests/components/asuswrt/test_device_tracker.py index 3954808aa37..ed733b54d25 100644 --- a/tests/components/asuswrt/test_device_tracker.py +++ b/tests/components/asuswrt/test_device_tracker.py @@ -1,5 +1,4 @@ """The tests for the ASUSWRT device tracker platform.""" -from unittest.mock import patch from homeassistant.components.asuswrt import ( CONF_DNSMASQ, @@ -10,13 +9,13 @@ from homeassistant.components.asuswrt import ( from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME from homeassistant.setup import async_setup_component -from tests.common import mock_coro_func +from tests.async_mock import AsyncMock, patch async def test_password_or_pub_key_required(hass): """Test creating an AsusWRT scanner without a pass or pubkey.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func() + AsusWrt().connection.async_connect = AsyncMock() AsusWrt().is_connected = False result = await async_setup_component( hass, DOMAIN, {DOMAIN: {CONF_HOST: "fake_host", CONF_USERNAME: "fake_user"}} @@ -27,7 +26,7 @@ async def test_password_or_pub_key_required(hass): async def test_network_unreachable(hass): """Test creating an AsusWRT scanner without a pass or pubkey.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func(exception=OSError) + AsusWrt().connection.async_connect = AsyncMock(side_effect=OSError) AsusWrt().is_connected = False result = await async_setup_component( hass, DOMAIN, {DOMAIN: {CONF_HOST: "fake_host", CONF_USERNAME: "fake_user"}} @@ -39,10 +38,8 @@ async def test_network_unreachable(hass): async def test_get_scanner_with_password_no_pubkey(hass): """Test creating an AsusWRT scanner with a password and no pubkey.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func() - AsusWrt().connection.async_get_connected_devices = mock_coro_func( - return_value={} - ) + AsusWrt().connection.async_connect = AsyncMock() + AsusWrt().connection.async_get_connected_devices = AsyncMock(return_value={}) result = await async_setup_component( hass, DOMAIN, @@ -62,7 +59,7 @@ async def test_get_scanner_with_password_no_pubkey(hass): async def test_specify_non_directory_path_for_dnsmasq(hass): """Test creating an AsusWRT scanner with a dnsmasq location which is not a valid directory.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func() + AsusWrt().connection.async_connect = AsyncMock() AsusWrt().is_connected = False result = await async_setup_component( hass, @@ -82,10 +79,8 @@ async def test_specify_non_directory_path_for_dnsmasq(hass): async def test_interface(hass): """Test creating an AsusWRT scanner using interface eth1.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func() - AsusWrt().connection.async_get_connected_devices = mock_coro_func( - return_value={} - ) + AsusWrt().connection.async_connect = AsyncMock() + AsusWrt().connection.async_get_connected_devices = AsyncMock(return_value={}) result = await async_setup_component( hass, DOMAIN, @@ -106,7 +101,7 @@ async def test_interface(hass): async def test_no_interface(hass): """Test creating an AsusWRT scanner using no interface.""" with patch("homeassistant.components.asuswrt.AsusWrt") as AsusWrt: - AsusWrt().connection.async_connect = mock_coro_func() + AsusWrt().connection.async_connect = AsyncMock() AsusWrt().is_connected = False result = await async_setup_component( hass, diff --git a/tests/components/cast/test_init.py b/tests/components/cast/test_init.py index 6971c071353..8f194668e56 100644 --- a/tests/components/cast/test_init.py +++ b/tests/components/cast/test_init.py @@ -1,19 +1,18 @@ """Tests for the Cast config flow.""" -from unittest.mock import patch from homeassistant import config_entries, data_entry_flow from homeassistant.components import cast from homeassistant.setup import async_setup_component -from tests.common import MockDependency, mock_coro +from tests.async_mock import patch async def test_creating_entry_sets_up_media_player(hass): """Test setting up Cast loads the media player.""" with patch( "homeassistant.components.cast.media_player.async_setup_entry", - return_value=mock_coro(True), - ) as mock_setup, MockDependency("pychromecast", "discovery"), patch( + return_value=True, + ) as mock_setup, patch( "pychromecast.discovery.discover_chromecasts", return_value=True ): result = await hass.config_entries.flow.async_init( @@ -34,8 +33,8 @@ async def test_creating_entry_sets_up_media_player(hass): async def test_configuring_cast_creates_entry(hass): """Test that specifying config will create an entry.""" with patch( - "homeassistant.components.cast.async_setup_entry", return_value=mock_coro(True) - ) as mock_setup, MockDependency("pychromecast", "discovery"), patch( + "homeassistant.components.cast.async_setup_entry", return_value=True + ) as mock_setup, patch( "pychromecast.discovery.discover_chromecasts", return_value=True ): await async_setup_component( @@ -49,8 +48,8 @@ async def test_configuring_cast_creates_entry(hass): async def test_not_configuring_cast_not_creates_entry(hass): """Test that no config will not create an entry.""" with patch( - "homeassistant.components.cast.async_setup_entry", return_value=mock_coro(True) - ) as mock_setup, MockDependency("pychromecast", "discovery"), patch( + "homeassistant.components.cast.async_setup_entry", return_value=True + ) as mock_setup, patch( "pychromecast.discovery.discover_chromecasts", return_value=True ): await async_setup_component(hass, cast.DOMAIN, {}) diff --git a/tests/components/cloud/__init__.py b/tests/components/cloud/__init__.py index 571b73e8d09..da7c6ff13d0 100644 --- a/tests/components/cloud/__init__.py +++ b/tests/components/cloud/__init__.py @@ -1,18 +1,17 @@ """Tests for the cloud component.""" -from unittest.mock import patch from homeassistant.components import cloud from homeassistant.components.cloud import const from homeassistant.setup import async_setup_component -from tests.common import mock_coro +from tests.async_mock import AsyncMock, patch async def mock_cloud(hass, config=None): """Mock cloud.""" assert await async_setup_component(hass, cloud.DOMAIN, {"cloud": config or {}}) cloud_inst = hass.data["cloud"] - with patch("hass_nabucasa.Cloud.run_executor", return_value=mock_coro()): + with patch("hass_nabucasa.Cloud.run_executor", AsyncMock(return_value=None)): await cloud_inst.start() diff --git a/tests/components/cloud/test_alexa_config.py b/tests/components/cloud/test_alexa_config.py index c239636e1d3..b064a5c9605 100644 --- a/tests/components/cloud/test_alexa_config.py +++ b/tests/components/cloud/test_alexa_config.py @@ -89,7 +89,7 @@ def patch_sync_helper(): to_update = [] to_remove = [] - async def sync_helper(to_upd, to_rem): + def sync_helper(to_upd, to_rem): to_update.extend([ent_id for ent_id in to_upd if ent_id not in to_update]) to_remove.extend([ent_id for ent_id in to_rem if ent_id not in to_remove]) return True diff --git a/tests/components/cloud/test_client.py b/tests/components/cloud/test_client.py index 0ce79daab15..21eb59ddc03 100644 --- a/tests/components/cloud/test_client.py +++ b/tests/components/cloud/test_client.py @@ -1,6 +1,4 @@ """Test the cloud.iot module.""" -from unittest.mock import MagicMock, patch - from aiohttp import web import pytest @@ -12,8 +10,7 @@ from homeassistant.setup import async_setup_component from . import mock_cloud, mock_cloud_prefs -from tests.async_mock import AsyncMock -from tests.common import mock_coro +from tests.async_mock import AsyncMock, MagicMock, patch from tests.components.alexa import test_smart_home as test_alexa @@ -131,7 +128,7 @@ async def test_handler_google_actions_disabled(hass, mock_cloud_fixture): """Test handler Google Actions when user has disabled it.""" mock_cloud_fixture._prefs[PREF_ENABLE_GOOGLE] = False - with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()): + with patch("hass_nabucasa.Cloud.start"): assert await async_setup_component(hass, "cloud", {}) reqid = "5711642932632160983" @@ -146,7 +143,7 @@ async def test_handler_google_actions_disabled(hass, mock_cloud_fixture): async def test_webhook_msg(hass): """Test webhook msg.""" - with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()): + with patch("hass_nabucasa.Cloud.start"): setup = await async_setup_component(hass, "cloud", {"cloud": {}}) assert setup cloud = hass.data["cloud"] diff --git a/tests/components/cloud/test_init.py b/tests/components/cloud/test_init.py index 10a7bc38c05..e174b080102 100644 --- a/tests/components/cloud/test_init.py +++ b/tests/components/cloud/test_init.py @@ -1,5 +1,4 @@ """Test the cloud component.""" -from unittest.mock import patch import pytest @@ -11,12 +10,12 @@ from homeassistant.core import Context from homeassistant.exceptions import Unauthorized from homeassistant.setup import async_setup_component -from tests.common import mock_coro +from tests.async_mock import patch async def test_constructor_loads_info_from_config(hass): """Test non-dev mode loads info from SERVERS constant.""" - with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()): + with patch("hass_nabucasa.Cloud.start"): result = await async_setup_component( hass, "cloud", @@ -63,17 +62,13 @@ async def test_remote_services(hass, mock_cloud_fixture, hass_read_only_user): assert hass.services.has_service(DOMAIN, "remote_connect") assert hass.services.has_service(DOMAIN, "remote_disconnect") - with patch( - "hass_nabucasa.remote.RemoteUI.connect", return_value=mock_coro() - ) as mock_connect: + with patch("hass_nabucasa.remote.RemoteUI.connect") as mock_connect: await hass.services.async_call(DOMAIN, "remote_connect", blocking=True) assert mock_connect.called assert cloud.client.remote_autostart - with patch( - "hass_nabucasa.remote.RemoteUI.disconnect", return_value=mock_coro() - ) as mock_disconnect: + with patch("hass_nabucasa.remote.RemoteUI.disconnect") as mock_disconnect: await hass.services.async_call(DOMAIN, "remote_disconnect", blocking=True) assert mock_disconnect.called @@ -82,9 +77,9 @@ async def test_remote_services(hass, mock_cloud_fixture, hass_read_only_user): # Test admin access required non_admin_context = Context(user_id=hass_read_only_user.id) - with patch( - "hass_nabucasa.remote.RemoteUI.connect", return_value=mock_coro() - ) as mock_connect, pytest.raises(Unauthorized): + with patch("hass_nabucasa.remote.RemoteUI.connect") as mock_connect, pytest.raises( + Unauthorized + ): await hass.services.async_call( DOMAIN, "remote_connect", blocking=True, context=non_admin_context ) @@ -92,7 +87,7 @@ async def test_remote_services(hass, mock_cloud_fixture, hass_read_only_user): assert mock_connect.called is False with patch( - "hass_nabucasa.remote.RemoteUI.disconnect", return_value=mock_coro() + "hass_nabucasa.remote.RemoteUI.disconnect" ) as mock_disconnect, pytest.raises(Unauthorized): await hass.services.async_call( DOMAIN, "remote_disconnect", blocking=True, context=non_admin_context @@ -103,7 +98,7 @@ async def test_remote_services(hass, mock_cloud_fixture, hass_read_only_user): async def test_startup_shutdown_events(hass, mock_cloud_fixture): """Test if the cloud will start on startup event.""" - with patch("hass_nabucasa.Cloud.stop", return_value=mock_coro()) as mock_stop: + with patch("hass_nabucasa.Cloud.stop") as mock_stop: hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP) await hass.async_block_till_done() @@ -114,7 +109,7 @@ async def test_setup_existing_cloud_user(hass, hass_storage): """Test setup with API push default data.""" user = await hass.auth.async_create_system_user("Cloud test") hass_storage[STORAGE_KEY] = {"version": 1, "data": {"cloud_user": user.id}} - with patch("hass_nabucasa.Cloud.start", return_value=mock_coro()): + with patch("hass_nabucasa.Cloud.start"): result = await async_setup_component( hass, "cloud", @@ -148,9 +143,7 @@ async def test_on_connect(hass, mock_cloud_fixture): assert len(hass.states.async_entity_ids("binary_sensor")) == 1 - with patch( - "homeassistant.helpers.discovery.async_load_platform", side_effect=mock_coro - ) as mock_load: + with patch("homeassistant.helpers.discovery.async_load_platform") as mock_load: await cl.iot._on_connect[-1]() await hass.async_block_till_done() diff --git a/tests/components/config/test_config_entries.py b/tests/components/config/test_config_entries.py index 358f952e191..cee86fc046e 100644 --- a/tests/components/config/test_config_entries.py +++ b/tests/components/config/test_config_entries.py @@ -1,7 +1,6 @@ """Test config entries API.""" from collections import OrderedDict -from unittest.mock import patch import pytest import voluptuous as vol @@ -13,10 +12,10 @@ from homeassistant.core import callback from homeassistant.generated import config_flows from homeassistant.setup import async_setup_component +from tests.async_mock import AsyncMock, patch from tests.common import ( MockConfigEntry, MockModule, - mock_coro_func, mock_entity_platform, mock_integration, ) @@ -228,7 +227,9 @@ async def test_create_account(hass, client): """Test a flow that creates an account.""" mock_entity_platform(hass, "config_flow.test", None) - mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True))) + mock_integration( + hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True)) + ) class TestFlow(core_ce.ConfigFlow): VERSION = 1 @@ -263,7 +264,9 @@ async def test_create_account(hass, client): async def test_two_step_flow(hass, client): """Test we can finish a two step flow.""" - mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True))) + mock_integration( + hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True)) + ) mock_entity_platform(hass, "config_flow.test", None) class TestFlow(core_ce.ConfigFlow): @@ -320,7 +323,9 @@ async def test_two_step_flow(hass, client): async def test_continue_flow_unauth(hass, client, hass_admin_user): """Test we can't finish a two step flow.""" - mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True))) + mock_integration( + hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True)) + ) mock_entity_platform(hass, "config_flow.test", None) class TestFlow(core_ce.ConfigFlow): @@ -516,7 +521,9 @@ async def test_options_flow(hass, client): async def test_two_step_options_flow(hass, client): """Test we can finish a two step options flow.""" - mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True))) + mock_integration( + hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True)) + ) class TestFlow(core_ce.ConfigFlow): @staticmethod @@ -666,7 +673,9 @@ async def test_update_entry_nonexisting(hass, hass_ws_client): async def test_ignore_flow(hass, hass_ws_client): """Test we can ignore a flow.""" assert await async_setup_component(hass, "config", {}) - mock_integration(hass, MockModule("test", async_setup_entry=mock_coro_func(True))) + mock_integration( + hass, MockModule("test", async_setup_entry=AsyncMock(return_value=True)) + ) mock_entity_platform(hass, "config_flow.test", None) class TestFlow(core_ce.ConfigFlow): diff --git a/tests/components/darksky/test_sensor.py b/tests/components/darksky/test_sensor.py index 2163a809b5e..2dc2a3ff30b 100644 --- a/tests/components/darksky/test_sensor.py +++ b/tests/components/darksky/test_sensor.py @@ -11,7 +11,7 @@ import requests_mock from homeassistant.components.darksky import sensor as darksky from homeassistant.setup import setup_component -from tests.common import MockDependency, get_test_home_assistant, load_fixture +from tests.common import get_test_home_assistant, load_fixture VALID_CONFIG_MINIMAL = { "sensor": { @@ -110,12 +110,11 @@ class TestDarkSkySetup(unittest.TestCase): """Stop everything that was started.""" self.hass.stop() - @MockDependency("forecastio") @patch( "homeassistant.components.darksky.sensor.forecastio.load_forecast", new=load_forecastMock, ) - def test_setup_with_config(self, mock_forecastio): + def test_setup_with_config(self): """Test the platform setup with configuration.""" setup_component(self.hass, "sensor", VALID_CONFIG_MINIMAL) @@ -129,12 +128,11 @@ class TestDarkSkySetup(unittest.TestCase): state = self.hass.states.get("sensor.dark_sky_summary") assert state is None - @MockDependency("forecastio") @patch( "homeassistant.components.darksky.sensor.forecastio.load_forecast", new=load_forecastMock, ) - def test_setup_with_language_config(self, mock_forecastio): + def test_setup_with_language_config(self): """Test the platform setup with language configuration.""" setup_component(self.hass, "sensor", VALID_CONFIG_LANG_DE) @@ -164,12 +162,11 @@ class TestDarkSkySetup(unittest.TestCase): ) assert not response - @MockDependency("forecastio") @patch( "homeassistant.components.darksky.sensor.forecastio.load_forecast", new=load_forecastMock, ) - def test_setup_with_alerts_config(self, mock_forecastio): + def test_setup_with_alerts_config(self): """Test the platform setup with alert configuration.""" setup_component(self.hass, "sensor", VALID_CONFIG_ALERTS) diff --git a/tests/components/emulated_roku/test_binding.py b/tests/components/emulated_roku/test_binding.py index 53b6217fcbc..61c93690548 100644 --- a/tests/components/emulated_roku/test_binding.py +++ b/tests/components/emulated_roku/test_binding.py @@ -14,7 +14,7 @@ from homeassistant.components.emulated_roku.binding import ( EmulatedRoku, ) -from tests.common import mock_coro_func +from tests.async_mock import AsyncMock async def test_events_fired_properly(hass): @@ -39,7 +39,7 @@ async def test_events_fired_properly(hass): nonlocal roku_event_handler roku_event_handler = handler - return Mock(start=mock_coro_func(), close=mock_coro_func()) + return Mock(start=AsyncMock(), close=AsyncMock()) def listener(event): events.append(event) diff --git a/tests/components/emulated_roku/test_init.py b/tests/components/emulated_roku/test_init.py index efdf330a876..8d58519ddf9 100644 --- a/tests/components/emulated_roku/test_init.py +++ b/tests/components/emulated_roku/test_init.py @@ -4,14 +4,14 @@ from unittest.mock import Mock, patch from homeassistant.components import emulated_roku from homeassistant.setup import async_setup_component -from tests.common import mock_coro_func +from tests.async_mock import AsyncMock async def test_config_required_fields(hass): """Test that configuration is successful with required fields.""" with patch.object(emulated_roku, "configured_servers", return_value=[]), patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", - return_value=Mock(start=mock_coro_func(), close=mock_coro_func()), + return_value=Mock(start=AsyncMock(), close=AsyncMock()), ): assert ( await async_setup_component( @@ -36,7 +36,7 @@ async def test_config_already_registered_not_configured(hass): """Test that an already registered name causes the entry to be ignored.""" with patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", - return_value=Mock(start=mock_coro_func(), close=mock_coro_func()), + return_value=Mock(start=AsyncMock(), close=AsyncMock()), ) as instantiate, patch.object( emulated_roku, "configured_servers", return_value=["Emulated Roku Test"] ): @@ -75,7 +75,7 @@ async def test_setup_entry_successful(hass): with patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", - return_value=Mock(start=mock_coro_func(), close=mock_coro_func()), + return_value=Mock(start=AsyncMock(), close=AsyncMock()), ) as instantiate: assert await emulated_roku.async_setup_entry(hass, entry) is True @@ -99,7 +99,7 @@ async def test_unload_entry(hass): with patch( "homeassistant.components.emulated_roku.binding.EmulatedRokuServer", - return_value=Mock(start=mock_coro_func(), close=mock_coro_func()), + return_value=Mock(start=AsyncMock(), close=AsyncMock()), ): assert await emulated_roku.async_setup_entry(hass, entry) is True diff --git a/tests/components/folder_watcher/test_init.py b/tests/components/folder_watcher/test_init.py index 0702e64b4f8..fa2cfc6d3f1 100644 --- a/tests/components/folder_watcher/test_init.py +++ b/tests/components/folder_watcher/test_init.py @@ -5,8 +5,6 @@ from unittest.mock import Mock, patch from homeassistant.components import folder_watcher from homeassistant.setup import async_setup_component -from tests.common import MockDependency - async def test_invalid_path_setup(hass): """Test that an invalid path is not set up.""" @@ -29,8 +27,7 @@ async def test_valid_path_setup(hass): ) -@MockDependency("watchdog", "events") -def test_event(mock_watchdog): +def test_event(): """Check that Home Assistant events are fired correctly on watchdog event.""" class MockPatternMatchingEventHandler: @@ -39,17 +36,20 @@ def test_event(mock_watchdog): def __init__(self, patterns): pass - mock_watchdog.events.PatternMatchingEventHandler = MockPatternMatchingEventHandler - hass = Mock() - handler = folder_watcher.create_event_handler(["*"], hass) - handler.on_created( - Mock(is_directory=False, src_path="/hello/world.txt", event_type="created") - ) - assert hass.bus.fire.called - assert hass.bus.fire.mock_calls[0][1][0] == folder_watcher.DOMAIN - assert hass.bus.fire.mock_calls[0][1][1] == { - "event_type": "created", - "path": "/hello/world.txt", - "file": "world.txt", - "folder": "/hello", - } + with patch( + "homeassistant.components.folder_watcher.PatternMatchingEventHandler", + MockPatternMatchingEventHandler, + ): + hass = Mock() + handler = folder_watcher.create_event_handler(["*"], hass) + handler.on_created( + Mock(is_directory=False, src_path="/hello/world.txt", event_type="created") + ) + assert hass.bus.fire.called + assert hass.bus.fire.mock_calls[0][1][0] == folder_watcher.DOMAIN + assert hass.bus.fire.mock_calls[0][1][1] == { + "event_type": "created", + "path": "/hello/world.txt", + "file": "world.txt", + "folder": "/hello", + } diff --git a/tests/components/http/test_view.py b/tests/components/http/test_view.py index 414ad4e8cb0..b298fff6674 100644 --- a/tests/components/http/test_view.py +++ b/tests/components/http/test_view.py @@ -15,7 +15,7 @@ from homeassistant.components.http.view import ( ) from homeassistant.exceptions import ServiceNotFound, Unauthorized -from tests.common import mock_coro_func +from tests.async_mock import AsyncMock @pytest.fixture @@ -38,7 +38,7 @@ async def test_handling_unauthorized(mock_request): """Test handling unauth exceptions.""" with pytest.raises(HTTPUnauthorized): await request_handler_factory( - Mock(requires_auth=False), mock_coro_func(exception=Unauthorized) + Mock(requires_auth=False), AsyncMock(side_effect=Unauthorized) )(mock_request) @@ -46,7 +46,7 @@ async def test_handling_invalid_data(mock_request): """Test handling unauth exceptions.""" with pytest.raises(HTTPBadRequest): await request_handler_factory( - Mock(requires_auth=False), mock_coro_func(exception=vol.Invalid("yo")) + Mock(requires_auth=False), AsyncMock(side_effect=vol.Invalid("yo")) )(mock_request) @@ -55,5 +55,5 @@ async def test_handling_service_not_found(mock_request): with pytest.raises(HTTPInternalServerError): await request_handler_factory( Mock(requires_auth=False), - mock_coro_func(exception=ServiceNotFound("test", "test")), + AsyncMock(side_effect=ServiceNotFound("test", "test")), )(mock_request) diff --git a/tests/components/iqvia/test_config_flow.py b/tests/components/iqvia/test_config_flow.py index 9345ff5b2ad..4cc30958b23 100644 --- a/tests/components/iqvia/test_config_flow.py +++ b/tests/components/iqvia/test_config_flow.py @@ -1,17 +1,8 @@ """Define tests for the IQVIA config flow.""" -import pytest - from homeassistant import data_entry_flow from homeassistant.components.iqvia import CONF_ZIP_CODE, DOMAIN, config_flow -from tests.common import MockConfigEntry, MockDependency - - -@pytest.fixture -def mock_pyiqvia(): - """Mock the pyiqvia library.""" - with MockDependency("pyiqvia") as mock_pyiqvia_: - yield mock_pyiqvia_ +from tests.common import MockConfigEntry async def test_duplicate_error(hass): @@ -26,7 +17,7 @@ async def test_duplicate_error(hass): assert result["errors"] == {CONF_ZIP_CODE: "identifier_exists"} -async def test_invalid_zip_code(hass, mock_pyiqvia): +async def test_invalid_zip_code(hass): """Test that an invalid ZIP code key throws an error.""" conf = {CONF_ZIP_CODE: "abcde"} @@ -48,7 +39,7 @@ async def test_show_form(hass): assert result["step_id"] == "user" -async def test_step_import(hass, mock_pyiqvia): +async def test_step_import(hass): """Test that the import step works.""" conf = {CONF_ZIP_CODE: "12345"} @@ -61,7 +52,7 @@ async def test_step_import(hass, mock_pyiqvia): assert result["data"] == {CONF_ZIP_CODE: "12345"} -async def test_step_user(hass, mock_pyiqvia): +async def test_step_user(hass): """Test that the user step works.""" conf = {CONF_ZIP_CODE: "12345"} diff --git a/tests/components/melissa/test_climate.py b/tests/components/melissa/test_climate.py index 8976f85f3d1..00c565aca8c 100644 --- a/tests/components/melissa/test_climate.py +++ b/tests/components/melissa/test_climate.py @@ -16,7 +16,8 @@ from homeassistant.components.melissa import DATA_MELISSA, climate as melissa from homeassistant.components.melissa.climate import MelissaClimate from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS -from tests.common import load_fixture, mock_coro_func +from tests.async_mock import AsyncMock +from tests.common import load_fixture _SERIAL = "12345678" @@ -24,17 +25,17 @@ _SERIAL = "12345678" def melissa_mock(): """Use this to mock the melissa api.""" api = Mock() - api.async_fetch_devices = mock_coro_func( + api.async_fetch_devices = AsyncMock( return_value=json.loads(load_fixture("melissa_fetch_devices.json")) ) - api.async_status = mock_coro_func( + api.async_status = AsyncMock( return_value=json.loads(load_fixture("melissa_status.json")) ) - api.async_cur_settings = mock_coro_func( + api.async_cur_settings = AsyncMock( return_value=json.loads(load_fixture("melissa_cur_settings.json")) ) - api.async_send = mock_coro_func(return_value=True) + api.async_send = AsyncMock(return_value=True) api.STATE_OFF = 0 api.STATE_ON = 1 @@ -276,7 +277,7 @@ async def test_send(hass): await thermostat.async_send({"fan": api.FAN_MEDIUM}) await hass.async_block_till_done() assert SPEED_MEDIUM == thermostat.fan_mode - api.async_send.return_value = mock_coro_func(return_value=False) + api.async_send.return_value = AsyncMock(return_value=False) thermostat._cur_settings = None await thermostat.async_send({"fan": api.FAN_LOW}) await hass.async_block_till_done() @@ -296,7 +297,7 @@ async def test_update(hass): await thermostat.async_update() assert SPEED_LOW == thermostat.fan_mode assert HVAC_MODE_HEAT == thermostat.state - api.async_status = mock_coro_func(exception=KeyError("boom")) + api.async_status = AsyncMock(side_effect=KeyError("boom")) await thermostat.async_update() mocked_warning.assert_called_once_with( "Unable to update entity %s", thermostat.entity_id diff --git a/tests/components/melissa/test_init.py b/tests/components/melissa/test_init.py index 892f4d60a44..7e174a4f8a0 100644 --- a/tests/components/melissa/test_init.py +++ b/tests/components/melissa/test_init.py @@ -1,23 +1,22 @@ """The test for the Melissa Climate component.""" from homeassistant.components import melissa -from tests.common import MockDependency, mock_coro_func +from tests.async_mock import AsyncMock, patch VALID_CONFIG = {"melissa": {"username": "********", "password": "********"}} async def test_setup(hass): """Test setting up the Melissa component.""" - with MockDependency("melissa") as mocked_melissa: - melissa.melissa = mocked_melissa - mocked_melissa.AsyncMelissa().async_connect = mock_coro_func() + with patch("melissa.AsyncMelissa") as mocked_melissa, patch.object( + melissa, "async_load_platform" + ): + mocked_melissa.return_value.async_connect = AsyncMock() await melissa.async_setup(hass, VALID_CONFIG) - mocked_melissa.AsyncMelissa.assert_called_with( - username="********", password="********" - ) + mocked_melissa.assert_called_with(username="********", password="********") assert melissa.DATA_MELISSA in hass.data assert isinstance( - hass.data[melissa.DATA_MELISSA], type(mocked_melissa.AsyncMelissa()) + hass.data[melissa.DATA_MELISSA], type(mocked_melissa.return_value), ) diff --git a/tests/components/mqtt/test_config_flow.py b/tests/components/mqtt/test_config_flow.py index aa72549152e..0990accec9f 100644 --- a/tests/components/mqtt/test_config_flow.py +++ b/tests/components/mqtt/test_config_flow.py @@ -1,18 +1,18 @@ """Test config flow.""" -from unittest.mock import patch import pytest from homeassistant.setup import async_setup_component -from tests.common import MockConfigEntry, mock_coro +from tests.async_mock import patch +from tests.common import MockConfigEntry @pytest.fixture(autouse=True) def mock_finish_setup(): """Mock out the finish setup method.""" with patch( - "homeassistant.components.mqtt.MQTT.async_connect", return_value=mock_coro(True) + "homeassistant.components.mqtt.MQTT.async_connect", return_value=True ) as mock_finish: yield mock_finish diff --git a/tests/components/reddit/test_sensor.py b/tests/components/reddit/test_sensor.py index c44c62fe080..51de8229347 100644 --- a/tests/components/reddit/test_sensor.py +++ b/tests/components/reddit/test_sensor.py @@ -3,7 +3,6 @@ import copy import unittest from unittest.mock import patch -from homeassistant.components.reddit import sensor as reddit_sensor from homeassistant.components.reddit.sensor import ( ATTR_BODY, ATTR_COMMENTS_NUMBER, @@ -20,7 +19,7 @@ from homeassistant.components.reddit.sensor import ( from homeassistant.const import CONF_MAXIMUM, CONF_PASSWORD, CONF_USERNAME from homeassistant.setup import setup_component -from tests.common import MockDependency, get_test_home_assistant +from tests.common import get_test_home_assistant VALID_CONFIG = { "sensor": { @@ -157,12 +156,10 @@ class TestRedditSetup(unittest.TestCase): """Stop everything that was started.""" self.hass.stop() - @MockDependency("praw") @patch("praw.Reddit", new=MockPraw) - def test_setup_with_valid_config(self, mock_praw): + def test_setup_with_valid_config(self): """Test the platform setup with Reddit configuration.""" - with patch.object(reddit_sensor, "praw", mock_praw): - setup_component(self.hass, "sensor", VALID_CONFIG) + setup_component(self.hass, "sensor", VALID_CONFIG) state = self.hass.states.get("sensor.reddit_worldnews") assert int(state.state) == MOCK_RESULTS_LENGTH @@ -184,9 +181,8 @@ class TestRedditSetup(unittest.TestCase): assert state.attributes[CONF_SORT_BY] == "hot" - @MockDependency("praw") @patch("praw.Reddit", new=MockPraw) - def test_setup_with_invalid_config(self, mock_praw): + def test_setup_with_invalid_config(self): """Test the platform setup with invalid Reddit configuration.""" setup_component(self.hass, "sensor", INVALID_SORT_BY_CONFIG) assert not self.hass.states.get("sensor.reddit_worldnews") diff --git a/tests/components/seventeentrack/test_sensor.py b/tests/components/seventeentrack/test_sensor.py index 10ec22f8b67..62f93d7cd70 100644 --- a/tests/components/seventeentrack/test_sensor.py +++ b/tests/components/seventeentrack/test_sensor.py @@ -14,7 +14,7 @@ from homeassistant.const import CONF_PASSWORD, CONF_USERNAME from homeassistant.setup import async_setup_component from homeassistant.util import utcnow -from tests.common import MockDependency, async_fire_time_changed +from tests.common import async_fire_time_changed VALID_CONFIG_MINIMAL = { "sensor": { @@ -110,15 +110,8 @@ class ProfileMock: return self.__class__.summary_data -@pytest.fixture(autouse=True, name="mock_py17track") -def fixture_mock_py17track(): - """Mock py17track dependency.""" - with MockDependency("py17track"): - yield - - @pytest.fixture(autouse=True, name="mock_client") -def fixture_mock_client(mock_py17track): +def fixture_mock_client(): """Mock py17track client.""" with mock.patch( "homeassistant.components.seventeentrack.sensor.SeventeenTrackClient", diff --git a/tests/components/tplink/test_init.py b/tests/components/tplink/test_init.py index d8e3f76cac3..290151b10cc 100644 --- a/tests/components/tplink/test_init.py +++ b/tests/components/tplink/test_init.py @@ -16,14 +16,12 @@ from homeassistant.components.tplink.common import ( from homeassistant.const import CONF_HOST from homeassistant.setup import async_setup_component -from tests.common import MockConfigEntry, MockDependency, mock_coro - -MOCK_PYHS100 = MockDependency("pyHS100") +from tests.common import MockConfigEntry, mock_coro async def test_creating_entry_tries_discover(hass): """Test setting up does discovery.""" - with MOCK_PYHS100, patch( + with patch( "homeassistant.components.tplink.async_setup_entry", return_value=mock_coro(True), ) as mock_setup, patch( @@ -47,9 +45,7 @@ async def test_creating_entry_tries_discover(hass): async def test_configuring_tplink_causes_discovery(hass): """Test that specifying empty config does discovery.""" - with MOCK_PYHS100, patch( - "homeassistant.components.tplink.common.Discover.discover" - ) as discover: + with patch("homeassistant.components.tplink.common.Discover.discover") as discover: discover.return_value = {"host": 1234} await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}}) await hass.async_block_till_done() @@ -177,7 +173,7 @@ async def test_is_dimmable(hass): async def test_configuring_discovery_disabled(hass): """Test that discover does not get called when disabled.""" - with MOCK_PYHS100, patch( + with patch( "homeassistant.components.tplink.async_setup_entry", return_value=mock_coro(True), ) as mock_setup, patch( @@ -226,7 +222,7 @@ async def test_platforms_are_initialized(hass): async def test_no_config_creates_no_entry(hass): """Test for when there is no tplink in config.""" - with MOCK_PYHS100, patch( + with patch( "homeassistant.components.tplink.async_setup_entry", return_value=mock_coro(True), ) as mock_setup: diff --git a/tests/components/twilio/test_init.py b/tests/components/twilio/test_init.py index 4c4d499a6d9..ee7f072a65c 100644 --- a/tests/components/twilio/test_init.py +++ b/tests/components/twilio/test_init.py @@ -5,34 +5,31 @@ from homeassistant import data_entry_flow from homeassistant.components import twilio from homeassistant.core import callback -from tests.common import MockDependency - async def test_config_flow_registers_webhook(hass, aiohttp_client): """Test setting up Twilio and sending webhook.""" - with MockDependency("twilio", "rest"), MockDependency("twilio", "twiml"): - with patch("homeassistant.util.get_local_ip", return_value="example.com"): - result = await hass.config_entries.flow.async_init( - "twilio", context={"source": "user"} - ) - assert result["type"] == data_entry_flow.RESULT_TYPE_FORM, result + with patch("homeassistant.util.get_local_ip", return_value="example.com"): + result = await hass.config_entries.flow.async_init( + "twilio", context={"source": "user"} + ) + assert result["type"] == data_entry_flow.RESULT_TYPE_FORM, result - result = await hass.config_entries.flow.async_configure(result["flow_id"], {}) - assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY - webhook_id = result["result"].data["webhook_id"] + result = await hass.config_entries.flow.async_configure(result["flow_id"], {}) + assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY + webhook_id = result["result"].data["webhook_id"] - twilio_events = [] + twilio_events = [] - @callback - def handle_event(event): - """Handle Twilio event.""" - twilio_events.append(event) + @callback + def handle_event(event): + """Handle Twilio event.""" + twilio_events.append(event) - hass.bus.async_listen(twilio.RECEIVED_DATA, handle_event) + hass.bus.async_listen(twilio.RECEIVED_DATA, handle_event) - client = await aiohttp_client(hass.http.app) - await client.post(f"/api/webhook/{webhook_id}", data={"hello": "twilio"}) + client = await aiohttp_client(hass.http.app) + await client.post(f"/api/webhook/{webhook_id}", data={"hello": "twilio"}) - assert len(twilio_events) == 1 - assert twilio_events[0].data["webhook_id"] == webhook_id - assert twilio_events[0].data["hello"] == "twilio" + assert len(twilio_events) == 1 + assert twilio_events[0].data["webhook_id"] == webhook_id + assert twilio_events[0].data["hello"] == "twilio" diff --git a/tests/components/updater/test_init.py b/tests/components/updater/test_init.py index 95875828c71..0d710907f59 100644 --- a/tests/components/updater/test_init.py +++ b/tests/components/updater/test_init.py @@ -6,7 +6,7 @@ from homeassistant.helpers.update_coordinator import UpdateFailed from homeassistant.setup import async_setup_component from tests.async_mock import patch -from tests.common import MockDependency, mock_component +from tests.common import mock_component NEW_VERSION = "10000.0" MOCK_VERSION = "10.0" @@ -17,13 +17,6 @@ MOCK_CONFIG = {updater.DOMAIN: {"reporting": True}} RELEASE_NOTES = "test release notes" -@pytest.fixture(autouse=True) -def mock_distro(): - """Mock distro dep.""" - with MockDependency("distro"): - yield - - @pytest.fixture(autouse=True) def mock_version(): """Mock current version.""" diff --git a/tests/components/wake_on_lan/test_init.py b/tests/components/wake_on_lan/test_init.py index c2ee0930895..6eb7afb29f4 100644 --- a/tests/components/wake_on_lan/test_init.py +++ b/tests/components/wake_on_lan/test_init.py @@ -2,21 +2,18 @@ import pytest import voluptuous as vol -from homeassistant.components import wake_on_lan from homeassistant.components.wake_on_lan import DOMAIN, SERVICE_SEND_MAGIC_PACKET from homeassistant.setup import async_setup_component -from tests.common import MockDependency +from tests.async_mock import patch async def test_send_magic_packet(hass): """Test of send magic packet service call.""" - with MockDependency("wakeonlan") as mocked_wakeonlan: + with patch("homeassistant.components.wake_on_lan.wakeonlan") as mocked_wakeonlan: mac = "aa:bb:cc:dd:ee:ff" bc_ip = "192.168.255.255" - wake_on_lan.wakeonlan = mocked_wakeonlan - await async_setup_component(hass, DOMAIN, {}) await hass.services.async_call( diff --git a/tests/components/yandex_transport/test_yandex_transport_sensor.py b/tests/components/yandex_transport/test_yandex_transport_sensor.py index f0664e4f045..f60e7ba5adf 100644 --- a/tests/components/yandex_transport/test_yandex_transport_sensor.py +++ b/tests/components/yandex_transport/test_yandex_transport_sensor.py @@ -8,12 +8,8 @@ import homeassistant.components.sensor as sensor from homeassistant.const import CONF_NAME import homeassistant.util.dt as dt_util -from tests.common import ( - MockDependency, - assert_setup_component, - async_setup_component, - load_fixture, -) +from tests.async_mock import patch +from tests.common import assert_setup_component, async_setup_component, load_fixture REPLY = json.loads(load_fixture("yandex_transport_reply.json")) @@ -21,8 +17,8 @@ REPLY = json.loads(load_fixture("yandex_transport_reply.json")) @pytest.fixture def mock_requester(): """Create a mock ya_ma module and YandexMapsRequester.""" - with MockDependency("ya_ma") as ya_ma: - instance = ya_ma.YandexMapsRequester.return_value + with patch("ya_ma.YandexMapsRequester") as requester: + instance = requester.return_value instance.get_stop_info.return_value = REPLY yield instance