|
16 | 16 | # under the License. |
17 | 17 | from __future__ import annotations |
18 | 18 |
|
| 19 | +import json |
19 | 20 | import os |
20 | 21 | from unittest import mock |
21 | 22 | from unittest.mock import MagicMock, PropertyMock, patch |
@@ -716,20 +717,31 @@ async def test_get_adf_pipeline_run_status_cancelled(self, mock_get_pipeline_run |
716 | 717 | assert response == mock_status |
717 | 718 |
|
718 | 719 | @pytest.mark.asyncio |
719 | | - @mock.patch(f"{MODULE}.AzureDataFactoryAsyncHook.get_connection") |
| 720 | + @mock.patch(f"{MODULE}.get_async_connection", new_callable=mock.AsyncMock) |
720 | 721 | @mock.patch(f"{MODULE}.AzureDataFactoryAsyncHook.get_async_conn") |
721 | | - async def test_get_pipeline_run_exception_without_resource(self, mock_conn, mock_get_connection): |
| 722 | + async def test_get_pipeline_run_exception_without_resource(self, mock_conn, mock_get_async_connection): |
722 | 723 | """ |
723 | 724 | Test get_pipeline_run function without passing the resource name to check the decorator function and |
724 | 725 | raise exception |
725 | 726 | """ |
726 | 727 | mock_connection = Connection(extra={"factory_name": DATAFACTORY_NAME}) |
727 | | - mock_get_connection.return_value = mock_connection |
| 728 | + mock_get_async_connection.return_value = mock_connection |
728 | 729 | mock_conn.return_value.pipeline_runs.get.return_value = MagicMock() |
729 | 730 | hook = AzureDataFactoryAsyncHook(AZURE_DATA_FACTORY_CONN_ID) |
730 | 731 | with pytest.raises(AirflowException): |
731 | 732 | await hook.get_pipeline_run(RUN_ID, None, DATAFACTORY_NAME) |
732 | 733 |
|
| 734 | + @staticmethod |
| 735 | + def _conn_with_raising_extra_dejson(extra: dict, login="clientId", password="clientSecret"): |
| 736 | + conn = mock.Mock() |
| 737 | + conn.login = login |
| 738 | + conn.password = password |
| 739 | + conn.extra = json.dumps(extra) |
| 740 | + type(conn).extra_dejson = PropertyMock( |
| 741 | + side_effect=RuntimeError("You cannot use AsyncToSync in the same thread as an async event loop") |
| 742 | + ) |
| 743 | + return conn |
| 744 | + |
733 | 745 | @pytest.mark.asyncio |
734 | 746 | @pytest.mark.parametrize( |
735 | 747 | "mocked_connection", |
@@ -786,6 +798,50 @@ async def test_get_async_conn(self, mocked_connection): |
786 | 798 | response = await hook.get_async_conn() |
787 | 799 | assert isinstance(response, DataFactoryManagementClient) |
788 | 800 |
|
| 801 | + @pytest.mark.asyncio |
| 802 | + async def test_get_async_conn_does_not_touch_extra_dejson(self): |
| 803 | + conn = self._conn_with_raising_extra_dejson( |
| 804 | + {"tenantId": "tenantId", "subscriptionId": "subscriptionId"} |
| 805 | + ) |
| 806 | + hook = AzureDataFactoryAsyncHook(AZURE_DATA_FACTORY_CONN_ID) |
| 807 | + with ( |
| 808 | + mock.patch(f"{MODULE}.get_async_connection", new=mock.AsyncMock(return_value=conn)), |
| 809 | + mock.patch(f"{MODULE}.AsyncClientSecretCredential"), |
| 810 | + mock.patch(f"{MODULE}.AsyncDataFactoryManagementClient") as mock_client, |
| 811 | + ): |
| 812 | + response = await hook.get_async_conn() |
| 813 | + assert response is mock_client.return_value |
| 814 | + |
| 815 | + @pytest.mark.asyncio |
| 816 | + async def test_get_async_conn_uses_get_async_connection(self): |
| 817 | + conn = self._conn_with_raising_extra_dejson( |
| 818 | + {"tenantId": "tenantId", "subscriptionId": "subscriptionId"} |
| 819 | + ) |
| 820 | + hook = AzureDataFactoryAsyncHook(AZURE_DATA_FACTORY_CONN_ID) |
| 821 | + with ( |
| 822 | + mock.patch( |
| 823 | + f"{MODULE}.get_async_connection", new=mock.AsyncMock(return_value=conn) |
| 824 | + ) as mock_get_async_connection, |
| 825 | + mock.patch(f"{MODULE}.AsyncClientSecretCredential"), |
| 826 | + mock.patch(f"{MODULE}.AsyncDataFactoryManagementClient"), |
| 827 | + ): |
| 828 | + await hook.get_async_conn() |
| 829 | + mock_get_async_connection.assert_awaited_once_with(AZURE_DATA_FACTORY_CONN_ID) |
| 830 | + |
| 831 | + @pytest.mark.asyncio |
| 832 | + @mock.patch(f"{MODULE}.AzureDataFactoryAsyncHook.get_async_conn") |
| 833 | + async def test_provide_targeted_factory_async_does_not_touch_extra_dejson(self, mock_get_async_conn): |
| 834 | + conn = self._conn_with_raising_extra_dejson( |
| 835 | + {"resource_group_name": RESOURCE_GROUP_NAME, "factory_name": DATAFACTORY_NAME} |
| 836 | + ) |
| 837 | + mock_get_async_conn.return_value.pipeline_runs.get = mock.AsyncMock(return_value=MagicMock()) |
| 838 | + hook = AzureDataFactoryAsyncHook(AZURE_DATA_FACTORY_CONN_ID) |
| 839 | + with mock.patch(f"{MODULE}.get_async_connection", new=mock.AsyncMock(return_value=conn)): |
| 840 | + await hook.get_pipeline_run(RUN_ID, None, None) |
| 841 | + mock_get_async_conn.return_value.pipeline_runs.get.assert_awaited_once_with( |
| 842 | + RESOURCE_GROUP_NAME, DATAFACTORY_NAME, RUN_ID |
| 843 | + ) |
| 844 | + |
789 | 845 | @pytest.mark.asyncio |
790 | 846 | @pytest.mark.parametrize( |
791 | 847 | "mocked_connection", |
@@ -904,10 +960,14 @@ def test_get_field_non_prefixed_extras(self): |
904 | 960 | @pytest.mark.asyncio |
905 | 961 | @mock.patch(f"{MODULE}.AzureDataFactoryAsyncHook.get_async_conn") |
906 | 962 | async def test_refresh_conn(self, mock_get_async_conn): |
907 | | - """Test refresh_conn method _conn is reset and get_async_conn is called""" |
| 963 | + """Test refresh_conn closes the async client before recreating it.""" |
908 | 964 | hook = AzureDataFactoryAsyncHook(AZURE_DATA_FACTORY_CONN_ID) |
| 965 | + mock_async_conn = mock.AsyncMock() |
| 966 | + hook._async_conn = mock_async_conn |
909 | 967 | await hook.refresh_conn() |
910 | 968 | assert not hook._conn |
| 969 | + mock_async_conn.close.assert_awaited_once() |
| 970 | + assert hook._async_conn is None |
911 | 971 | assert mock_get_async_conn.called |
912 | 972 |
|
913 | 973 | @pytest.mark.asyncio |
|
0 commit comments