from unittest import mock import pytest from anydi import Container from freezegun import freeze_time from starlette.testclient import TestClient from dmp.adapters.fivetran.models import ConnectCard from dmp.app_connections.enums import AppConnectionStatus from dmp.tiktok.dtos import ( TikTokAdAccountOverview, TikTokUserAdAccountLabel, TikTokUserConnectionAdAccount, TikTokUserConnectionResponse, ) from dmp.tiktok.enums import TikTokUserConnectionStatus from dmp.tiktok.handlers import ( AssignLabelsToTikTokUserAdAccountsHandler, ConnectTikTokAdReportingHandler, ConnectTikTokUserHandler, DeleteTikTokAdAccountsHandler, DeleteTikTokUserAdAccountHandler, GetTikTokAdAccountsHandler, GetTikTokAdAccountsV2Handler, GetTikTokAdAccountsV2Response, GetTikTokAdReportingConnectionHandler, GetTikTokAdReportingConnectionResponse, GetTikTokAudienceShareHandler, GetTikTokAudienceShareStatusHandler, GetTikTokAudienceShareStatusResponse, GetTikTokUserAdAccountsHandler, GetTikTokUserConnectionHandler, NotifyTikTokAdReportingSyncCompletedHandler, RefreshTikTokAdReportingConnectionHandler, ShareTikTokAudienceHandler, SyncTikTokFivetranTablesStateHandler, UpdateTikTokAudienceHandler, ) from dmp.tiktok.handlers.get_ad_accounts_v2 import GetTikTokAdAccountsV2Request from dmp.tiktok.handlers.get_audience_share import GetTikTokAudienceShareResponse from dmp.tiktok.models import ( TikTokAdAccount, TikTokAdReportingConnection, TikTokAudience, ) from tests.unit.equals import IsISODatetime from tests.unit.faker import FakerTyped from tests.unit.types import BuildModel, CreateModel def test_connect_tiktok_user( client: TestClient, build_model: BuildModel, fake: FakerTyped, container: Container ) -> None: access_token = fake.pystr() user_id = fake.pystr() user_name = fake.pystr() user_connection_ad_account = build_model(TikTokUserConnectionAdAccount) handler_mock = mock.MagicMock(spec=ConnectTikTokUserHandler) handler_mock.handle.return_value = TikTokUserConnectionResponse( user_id=user_id, user_name=user_name, status=TikTokUserConnectionStatus.CONNECTED, ad_accounts=[user_connection_ad_account], ) with container.override(ConnectTikTokUserHandler, handler_mock): response = client.post( "/tiktok/user/connection", json={ "accessToken": access_token, }, ) assert response.status_code == 200 assert response.json() == { "userId": user_id, "userName": user_name, "status": "CONNECTED", "adAccounts": [ { "id": user_connection_ad_account.id, "externalId": user_connection_ad_account.external_id, "name": user_connection_ad_account.name, "businessCenterName": user_connection_ad_account.business_center_name, } ], "adAccountsCount": 1, } @pytest.mark.db def test_connect_tiktok_ad_reporting_connection( client: TestClient, fake: FakerTyped, container: Container, build_model: BuildModel ) -> None: connection = build_model( TikTokAdReportingConnection, status=AppConnectionStatus.CONNECTED, ) connect_card = build_model(ConnectCard) handler_mock = mock.MagicMock(spec=ConnectTikTokAdReportingHandler) handler_mock.handle.return_value = connection, connect_card with container.override(ConnectTikTokAdReportingHandler, handler_mock): response = client.post( "/tiktok/ad-reporting/connection", json={"redirectUri": fake.url(), "userId": fake.pystr()}, ) assert response.status_code == 200 assert response.json() == { "connectionId": connection.id, "connectCardUri": connect_card.uri, } @pytest.mark.db def test_get_tiktok_ad_reporting_connection_status( client: TestClient, fake: FakerTyped, create_model: CreateModel, container: Container, identity_id: str, ) -> None: user_id = fake.pystr() connection = create_model( TikTokAdReportingConnection, status=AppConnectionStatus.CONNECTED, identity_id=identity_id, ad_accounts=[create_model(TikTokAdAccount)], ) handler_mock = mock.MagicMock(spec=GetTikTokAdReportingConnectionHandler) handler_mock.handle.return_value = GetTikTokAdReportingConnectionResponse( status=connection.status, ad_accounts_count=connection.ad_accounts_count, ) with container.override(GetTikTokAdReportingConnectionHandler, handler_mock): response = client.get( "/tiktok/ad-reporting/connection", params={"userId": user_id} ) assert response.status_code == 200 assert response.json() == { "status": connection.status, "adAccountsCount": 1, } @pytest.mark.db def test_refresh_tiktok_ad_reporting_connection( client: TestClient, container: Container, create_model: CreateModel ) -> None: connection = create_model( TikTokAdReportingConnection, status=AppConnectionStatus.CONNECTED, ) handler_mock = mock.MagicMock(spec=RefreshTikTokAdReportingConnectionHandler) handler_mock.handle.return_value = connection with container.override(RefreshTikTokAdReportingConnectionHandler, handler_mock): response = client.put( "/tiktok/ad-reporting/connection/refresh", json={"fivetranConnectorId": connection.fivetran_connector_id}, ) assert response.status_code == 204 def test_get_tiktok_user_connection( client: TestClient, build_model: BuildModel, fake: FakerTyped, container: Container ) -> None: user_id = fake.pystr() user_name = fake.pystr() user_connection_ad_account = build_model(TikTokUserConnectionAdAccount) handler_mock = mock.MagicMock(spec=GetTikTokUserConnectionHandler) handler_mock.handle.return_value = TikTokUserConnectionResponse( user_id=user_id, user_name=user_name, status=TikTokUserConnectionStatus.CONNECTED, ad_accounts=[user_connection_ad_account], ) with container.override(GetTikTokUserConnectionHandler, handler_mock): response = client.get( "/tiktok/user/connection", params={ "userId": user_id, }, ) assert response.status_code == 200 assert response.json() == { "userId": user_id, "userName": user_name, "status": "CONNECTED", "adAccounts": [ { "id": user_connection_ad_account.id, "externalId": user_connection_ad_account.external_id, "name": user_connection_ad_account.name, "businessCenterName": user_connection_ad_account.business_center_name, } ], "adAccountsCount": 1, } def test_get_tiktok_user_connection_error_response( client: TestClient, fake: FakerTyped, container: Container ) -> None: handler_mock = mock.MagicMock(spec=GetTikTokUserConnectionHandler) handler_mock.handle.return_value = TikTokUserConnectionResponse( user_id=None, user_name=None, status=TikTokUserConnectionStatus.NOT_CONNECTED, ad_accounts=[], ) with container.override(GetTikTokUserConnectionHandler, handler_mock): response = client.get( "/tiktok/user/connection", params={ "userId": fake.pystr(), }, ) assert response.status_code == 200 assert response.json() == { "userId": None, "userName": None, "status": "NOT_CONNECTED", "adAccounts": [], "adAccountsCount": 0, } def test_get_tiktok_user_ad_accounts( client: TestClient, build_model: BuildModel, fake: FakerTyped, identity_id: str, container: Container, ) -> None: user_id = fake.pystr() ad_account_1 = build_model( TikTokUserAdAccountLabel, identity_id=identity_id, user_id=user_id ) ad_account_2 = build_model( TikTokUserAdAccountLabel, vendor_id=None, subaccount_id=None, identity_id=identity_id, user_id=user_id, ) handler_mock = mock.MagicMock(spec=GetTikTokUserAdAccountsHandler) handler_mock.handle.return_value = [ad_account_1, ad_account_2] with container.override(GetTikTokUserAdAccountsHandler, handler_mock): response = client.get("/tiktok/user/ad-accounts/", params={"userId": user_id}) assert response.status_code == 200 assert response.json() == [ { "id": ad_account_1.id, "name": ad_account_1.name, "businessCenterName": ad_account_1.business_center_name, "vendorId": ad_account_1.vendor_id, "subaccountId": ad_account_1.subaccount_id, }, { "id": ad_account_2.id, "name": ad_account_2.name, "businessCenterName": ad_account_2.business_center_name, "vendorId": ad_account_2.vendor_id, "subaccountId": ad_account_2.subaccount_id, }, ] @pytest.mark.db def test_assign_tiktok_user_ad_account_labels( client: TestClient, fake: FakerTyped, container: Container ) -> None: handler_mock = mock.MagicMock(spec=AssignLabelsToTikTokUserAdAccountsHandler) handler_mock.handle.return_value = None with container.override(AssignLabelsToTikTokUserAdAccountsHandler, handler_mock): response = client.post( "/tiktok/user/ad-accounts", json=[ { "adAccountId": fake.pystr(), "vendorId": 7123, "subaccountId": 0, }, { "adAccountId": fake.pystr(), "vendorId": 7123, "subaccountId": 0, }, ], ) assert response.status_code == 204 @pytest.mark.db def test_assign_tiktok_user_ad_account_labels_validate_unique_ad_account_ids( client: TestClient, fake: FakerTyped, container: Container ) -> None: handler_mock = mock.MagicMock(spec=AssignLabelsToTikTokUserAdAccountsHandler) handler_mock.handle.return_value = None ad_account_id = fake.pystr() with container.override(AssignLabelsToTikTokUserAdAccountsHandler, handler_mock): response = client.post( "/tiktok/user/ad-accounts", json=[ { "adAccountId": ad_account_id, "vendorId": 7123, "subaccountId": 0, }, { "adAccountId": ad_account_id, "vendorId": 7123, "subaccountId": 0, }, ], ) assert response.status_code == 422 def test_get_tiktok_ad_accounts( client: TestClient, build_model: BuildModel, container: Container ) -> None: ad_account_1 = build_model(TikTokAdAccountOverview) ad_account_2 = build_model(TikTokAdAccountOverview) handler_mock = mock.MagicMock(spec=GetTikTokAdAccountsHandler) handler_mock.handle.return_value = [ad_account_1, ad_account_2] with container.override(GetTikTokAdAccountsHandler, handler_mock): response = client.get("/tiktok/ad-accounts") assert response.status_code == 200 assert response.json() == [ { "id": ad_account_1.id, "userAdAccountId": ad_account_1.user_ad_account_id, "userId": ad_account_1.user_id, "externalId": ad_account_1.external_id, "name": ad_account_1.name, "businessCenterName": ad_account_1.business_center_name, "vendorId": ad_account_1.vendor_id, "subaccountId": ad_account_1.subaccount_id, "isSelfConnected": ad_account_1.is_self_connected, "userConnectionStatus": ad_account_1.user_connection_status, "userSelfConnected": ad_account_1.user_self_connected, "adReportingConnectionStatus": ad_account_1.ad_reporting_connection_status, "adReportingSelfConnected": ad_account_1.ad_reporting_self_connected, "sharingUserId": ad_account_1.sharing_user_id, "reportingUserId": ad_account_1.reporting_user_id, "campaignsCount": ad_account_1.campaigns_count, }, { "id": ad_account_2.id, "userAdAccountId": ad_account_2.user_ad_account_id, "userId": ad_account_2.user_id, "externalId": ad_account_2.external_id, "name": ad_account_2.name, "businessCenterName": ad_account_2.business_center_name, "vendorId": ad_account_2.vendor_id, "subaccountId": ad_account_2.subaccount_id, "isSelfConnected": ad_account_2.is_self_connected, "userConnectionStatus": ad_account_2.user_connection_status, "userSelfConnected": ad_account_2.user_self_connected, "adReportingConnectionStatus": ad_account_2.ad_reporting_connection_status, "adReportingSelfConnected": ad_account_2.ad_reporting_self_connected, "sharingUserId": ad_account_2.sharing_user_id, "reportingUserId": ad_account_2.reporting_user_id, "campaignsCount": ad_account_2.campaigns_count, }, ] def test_delete_tiktok_user_ad_account( client: TestClient, fake: FakerTyped, container: Container ) -> None: handler_mock = mock.MagicMock(spec=DeleteTikTokUserAdAccountHandler) handler_mock.handle.return_value = None with container.override(DeleteTikTokUserAdAccountHandler, handler_mock): response = client.delete( f"/tiktok/user/ad-accounts/{fake.pystr()}", params={"userId": fake.pystr()} ) assert response.status_code == 204 def test_delete_tiktok_ad_accounts( client: TestClient, fake: FakerTyped, container: Container ) -> None: handler_mock = mock.MagicMock(spec=DeleteTikTokAdAccountsHandler) handler_mock.handle.return_value = None with container.override(DeleteTikTokAdAccountsHandler, handler_mock): response = client.delete( f"/tiktok/ad-accounts/{fake.pystr()}", params={ "identityId": fake.uuid4_string(), "vendorId": 7123, "subaccountId": 0, }, ) assert response.status_code == 204 def test_handle_dbt_sync(client: TestClient, container: Container) -> None: handler_mock = mock.MagicMock(spec=NotifyTikTokAdReportingSyncCompletedHandler) handler_mock.handle.return_value = None with container.override(NotifyTikTokAdReportingSyncCompletedHandler, handler_mock): response = client.post( "/tiktok/ad-reporting/handle-dbt-sync", ) assert response.status_code == 204 @pytest.mark.db @freeze_time("2020-01-01") def test_share_tiktok_audience( client: TestClient, create_model: CreateModel, container: Container ) -> None: ad_account = create_model(TikTokAdAccount) tiktok_audience = create_model(TikTokAudience, ad_account=ad_account) handler_mock = mock.MagicMock(spec=ShareTikTokAudienceHandler) handler_mock.handle.return_value = tiktok_audience with container.override(ShareTikTokAudienceHandler, handler_mock): response = client.post( "/tiktok/audiences", json={ "audienceId": tiktok_audience.audience_id, "adAccountId": tiktok_audience.ad_account_id, "justification": tiktok_audience.share.justification, "reasonNotes": tiktok_audience.share.reason_notes, }, ) assert response.status_code == 201 assert response.json() == { "id": tiktok_audience.id, "externalId": tiktok_audience.external_id, "name": tiktok_audience.name, "fansCount": tiktok_audience.fans_count, "createdAt": IsISODatetime(tiktok_audience.created_at), } @pytest.mark.db def test_get_tiktok_audience_share_status( client: TestClient, create_model: CreateModel, container: Container ) -> None: tiktok_audience = create_model(TikTokAudience) handler_mock = mock.MagicMock(spec=GetTikTokAudienceShareStatusHandler) handler_mock.handle.return_value = GetTikTokAudienceShareStatusResponse( audience_id=tiktok_audience.id, audience_name=tiktok_audience.name, ad_account_name=tiktok_audience.ad_account.name or "", status=tiktok_audience.share.status, fans_count=tiktok_audience.fans_count, processed_fans=tiktok_audience.share.processed_fans, progress=0.0, seconds_remaining=None, url=tiktok_audience.url, ) with container.override(GetTikTokAudienceShareStatusHandler, handler_mock): response = client.get(f"/tiktok/audiences/{tiktok_audience.id}/share-status") assert response.status_code == 200 assert response.json() == { "audienceId": tiktok_audience.id, "audienceName": tiktok_audience.name, "adAccountName": tiktok_audience.ad_account.name, "status": tiktok_audience.share.status, "fansCount": tiktok_audience.fans_count, "processedFans": tiktok_audience.share.processed_fans, "progress": 0.0, "secondsRemaining": None, "url": tiktok_audience.url, } @pytest.mark.db def test_get_tiktok_audience_share_status_without_updated_external_id( client: TestClient, create_model: CreateModel, container: Container ) -> None: tiktok_audience = create_model(TikTokAudience, external_id=None) handler_mock = mock.MagicMock(spec=GetTikTokAudienceShareStatusHandler) handler_mock.handle.return_value = GetTikTokAudienceShareStatusResponse( audience_id=tiktok_audience.id, audience_name=tiktok_audience.name, ad_account_name=tiktok_audience.ad_account.name or "", status=tiktok_audience.share.status, fans_count=tiktok_audience.fans_count, processed_fans=tiktok_audience.share.processed_fans, progress=0.0, seconds_remaining=None, url=tiktok_audience.url, ) with container.override(GetTikTokAudienceShareStatusHandler, handler_mock): response = client.get(f"/tiktok/audiences/{tiktok_audience.id}/share-status") assert response.status_code == 200 assert response.json() == { "audienceId": tiktok_audience.id, "audienceName": tiktok_audience.name, "adAccountName": tiktok_audience.ad_account.name, "status": tiktok_audience.share.status, "fansCount": tiktok_audience.fans_count, "processedFans": tiktok_audience.share.processed_fans, "progress": 0.0, "secondsRemaining": None, "url": tiktok_audience.url, } @pytest.mark.db def test_get_tiktok_audience_share( client: TestClient, fake: FakerTyped, create_model: CreateModel, container: Container, ) -> None: tiktok_audience = create_model(TikTokAudience) access_token = fake.encrypted_token() handler_mock = mock.MagicMock(spec=GetTikTokAudienceShareHandler) handler_mock.handle.return_value = GetTikTokAudienceShareResponse( audience_id=tiktok_audience.id, audience_name=tiktok_audience.name, audience_external_id=tiktok_audience.external_id, fans_count=tiktok_audience.fans_count, ad_account_external_id=tiktok_audience.ad_account.external_id, user_access_token=access_token, ) with container.override(GetTikTokAudienceShareHandler, handler_mock): response = client.get(f"/tiktok/audience-shares/{tiktok_audience.share_id}") assert response.status_code == 200 assert response.json() == { "audienceId": tiktok_audience.id, "audienceName": tiktok_audience.name, "audienceExternalId": tiktok_audience.external_id, "fansCount": tiktok_audience.fans_count, "adAccountExternalId": tiktok_audience.ad_account.external_id, "userAccessToken": access_token, } @pytest.mark.db def test_get_tiktok_audience_share_with_none_external_id( client: TestClient, fake: FakerTyped, create_model: CreateModel, container: Container, ) -> None: tiktok_audience = create_model(TikTokAudience, external_id=None) access_token = fake.encrypted_token() handler_mock = mock.MagicMock(spec=GetTikTokAudienceShareHandler) handler_mock.handle.return_value = GetTikTokAudienceShareResponse( audience_id=tiktok_audience.id, audience_name=tiktok_audience.name, audience_external_id=tiktok_audience.external_id, fans_count=tiktok_audience.fans_count, ad_account_external_id=tiktok_audience.ad_account.external_id, user_access_token=access_token, ) with container.override(GetTikTokAudienceShareHandler, handler_mock): response = client.get(f"/tiktok/audience-shares/{tiktok_audience.share_id}") assert response.status_code == 200 assert response.json() == { "audienceId": tiktok_audience.id, "audienceName": tiktok_audience.name, "audienceExternalId": None, "fansCount": tiktok_audience.fans_count, "adAccountExternalId": tiktok_audience.ad_account.external_id, "userAccessToken": access_token, } @pytest.mark.db @freeze_time("2020-01-01") def test_update_tiktok_audience( client: TestClient, create_model: CreateModel, container: Container ) -> None: ad_account = create_model(TikTokAdAccount) tiktok_audience = create_model(TikTokAudience, ad_account=ad_account) handler_mock = mock.MagicMock(spec=UpdateTikTokAudienceHandler) handler_mock.handle.return_value = tiktok_audience with container.override(UpdateTikTokAudienceHandler, handler_mock): response = client.patch( f"/tiktok/audiences/{tiktok_audience.id}", json={ "externalId": tiktok_audience.external_id, }, ) assert response.status_code == 200 assert response.json() == { "id": tiktok_audience.id, "externalId": tiktok_audience.external_id, "name": tiktok_audience.name, "fansCount": tiktok_audience.fans_count, "createdAt": IsISODatetime(tiktok_audience.created_at), } def test_sync_fivetran_tables_state( client: TestClient, fake: FakerTyped, container: Container, ) -> None: handler_mock = mock.MagicMock(spec=SyncTikTokFivetranTablesStateHandler) handler_mock.handle.return_value = [] with container.override(SyncTikTokFivetranTablesStateHandler, handler_mock): response = client.post( "/tiktok/sync-fivetran-tables-state", json={ "fivetranConnectorId": fake.pystr(), }, ) assert response.status_code == 200 def test_sync_fivetran_tables_state_all_connections( client: TestClient, container: Container ) -> None: handler_mock = mock.MagicMock(spec=SyncTikTokFivetranTablesStateHandler) handler_mock.handle.return_value = [] with container.override(SyncTikTokFivetranTablesStateHandler, handler_mock): response = client.post( "/tiktok/sync-fivetran-tables-state", json={ "fivetranConnectorId": None, }, ) assert response.status_code == 200 def test_get_tiktok_ad_accounts_v2( client: TestClient, build_model: BuildModel, container: Container, ) -> None: ad_account_1 = build_model(TikTokAdAccountOverview) ad_account_2 = build_model(TikTokAdAccountOverview) handler_mock = mock.MagicMock(spec=GetTikTokAdAccountsV2Handler) handler_mock.handle.return_value = GetTikTokAdAccountsV2Response( total=2, items=[ad_account_1, ad_account_2], ) with container.override(GetTikTokAdAccountsV2Handler, handler_mock): response = client.get("/tiktok/ad-accounts-v2") assert response.status_code == 200 assert response.json() == { "total": 2, "limit": 10, "offset": 0, "items": [ { "id": ad_account_1.id, "userAdAccountId": ad_account_1.user_ad_account_id, "userId": ad_account_1.user_id, "externalId": ad_account_1.external_id, "name": ad_account_1.name, "businessCenterName": ad_account_1.business_center_name, "vendorId": ad_account_1.vendor_id, "subaccountId": ad_account_1.subaccount_id, "isSelfConnected": ad_account_1.is_self_connected, "userConnectionStatus": ad_account_1.user_connection_status, "userSelfConnected": ad_account_1.user_self_connected, "adReportingConnectionStatus": ad_account_1.ad_reporting_connection_status, "adReportingSelfConnected": ad_account_1.ad_reporting_self_connected, "sharingUserId": ad_account_1.sharing_user_id, "reportingUserId": ad_account_1.reporting_user_id, "campaignsCount": ad_account_1.campaigns_count, }, { "id": ad_account_2.id, "userAdAccountId": ad_account_2.user_ad_account_id, "userId": ad_account_2.user_id, "externalId": ad_account_2.external_id, "name": ad_account_2.name, "businessCenterName": ad_account_2.business_center_name, "vendorId": ad_account_2.vendor_id, "subaccountId": ad_account_2.subaccount_id, "isSelfConnected": ad_account_2.is_self_connected, "userConnectionStatus": ad_account_2.user_connection_status, "userSelfConnected": ad_account_2.user_self_connected, "adReportingConnectionStatus": ad_account_2.ad_reporting_connection_status, "adReportingSelfConnected": ad_account_2.ad_reporting_self_connected, "sharingUserId": ad_account_2.sharing_user_id, "reportingUserId": ad_account_2.reporting_user_id, "campaignsCount": ad_account_2.campaigns_count, }, ], } def test_get_tiktok_ad_accounts_v2_with_filters( client: TestClient, build_model: BuildModel, fake: FakerTyped, container: Container, ) -> None: ad_account = build_model(TikTokAdAccountOverview) vendor_id = fake.integer() subaccount_id = fake.integer() handler_mock = mock.MagicMock(spec=GetTikTokAdAccountsV2Handler) handler_mock.handle.return_value = GetTikTokAdAccountsV2Response( total=1, items=[ad_account], ) with container.override(GetTikTokAdAccountsV2Handler, handler_mock): response = client.get( "/tiktok/ad-accounts-v2", params={ "vendorId": vendor_id, "subaccountId": subaccount_id, "limit": 5, "offset": 10, }, ) assert response.status_code == 200 body = response.json() assert body["total"] == 1 assert body["limit"] == 5 assert body["offset"] == 10 assert len(body["items"]) == 1 call_request = handler_mock.handle.call_args[0][0] assert call_request.vendor_id == vendor_id assert call_request.subaccount_id == subaccount_id assert call_request.limit == 5 assert call_request.offset == 10 def test_get_tiktok_ad_accounts_v2_with_order_by( client: TestClient, build_model: BuildModel, container: Container, ) -> None: ad_account = build_model(TikTokAdAccountOverview) handler_mock = mock.MagicMock(spec=GetTikTokAdAccountsV2Handler) handler_mock.handle.return_value = GetTikTokAdAccountsV2Response( total=1, items=[ad_account], ) with container.override(GetTikTokAdAccountsV2Handler, handler_mock): response = client.get( "/tiktok/ad-accounts-v2", params={"orderBy": ["campaignsCount.desc", "name.asc"]}, ) assert response.status_code == 200 call_request = handler_mock.handle.call_args[0][0] assert call_request.order_by == ["campaignsCount.desc", "name.asc"] def test_get_tiktok_ad_accounts_v2_defaults_order_by( client: TestClient, container: Container, ) -> None: handler_mock = mock.MagicMock(spec=GetTikTokAdAccountsV2Handler) handler_mock.handle.return_value = GetTikTokAdAccountsV2Response(total=0, items=[]) with container.override(GetTikTokAdAccountsV2Handler, handler_mock): response = client.get("/tiktok/ad-accounts-v2") assert response.status_code == 200 call_request = handler_mock.handle.call_args[0][0] assert call_request.order_by == GetTikTokAdAccountsV2Request.DEFAULT_ORDER_BY