I am creating a parameterized Mock PyTest to test API behaviors. I am trying to simplify the test code by testing the instance modified behavior, e.g. throw and exception, and the default behavior, i.e. load JSON from file vs. calling REST API.
I do not know how to add an array entry to represent the "default" mock behavior?
@pytest.mark.parametrize(
("get_nearby_sensors_mock", "get_nearby_sensors_errors"),
[
(AsyncMock(side_effect=Exception), {CONF_BASE: CONF_UNKNOWN}),
(AsyncMock(side_effect=PurpleAirError), {CONF_BASE: CONF_UNKNOWN}),
(AsyncMock(side_effect=InvalidApiKeyError), {CONF_BASE: CONF_INVALID_API_KEY}),
(AsyncMock(return_value=[]), {CONF_BASE: CONF_NO_SENSORS_FOUND}),
# What do I do here?
# (AsyncMock(api.sensors, "async_get_nearby_sensors")) does not work as api is not in scope?
# (AsyncMock(side_effect=None), {}) does not call the default fixture?
(AsyncMock(), {}),
],
)
async def test_validate_coordinates(
hass: HomeAssistant,
mock_aiopurpleair,
api,
get_nearby_sensors_mock,
get_nearby_sensors_errors,
) -> None:
"""Test validate_coordinates errors."""
with (
patch.object(api, "async_check_api_key"),
patch.object(api.sensors, "async_get_nearby_sensors", get_nearby_sensors_mock),
):
result: ConfigValidation = await ConfigValidation.async_validate_coordinates(
hass, TEST_API_KEY, TEST_LATITUDE, TEST_LONGITUDE, TEST_RADIUS
)
assert result.errors == get_nearby_sensors_errors
if result.errors == {}:
assert result.data is not None
else:
assert result.data is None
How do I add a parameter for the "default behavior" of patch.object(api.sensors, "async_get_nearby_sensors")
that will use the fixture to load data from canned JSON file?
Why mock; async_validate_coordinates()
calls async_check_api_key()
that needs to be mocked to pass, and async_get_nearby_sensors()
that is mocked with a fixture to return data from a JSON file.
For ref this is the conftest.py
file.
As a workaround, you could deal with any api-related case inside the function, where the api is known.
For this single-use, I would use None
to trigger the default case
@pytest.mark.parametrize(
("get_nearby_sensors_mock", "get_nearby_sensors_errors"),
[
# [...]
(None, {}),
],
)
async def test_validate_coordinates(
hass: HomeAssistant,
mock_aiopurpleair,
api,
get_nearby_sensors_mock,
get_nearby_sensors_errors,
) -> None:
"""Test validate_coordinates errors."""
if get_nearby_sensors_mock is None:
get_nearby_sensors_mock = AsyncMock(api.sensors, "async_get_nearby_sensors")
with (patch.object( # [...]