1- from unittest .mock import Mock , patch
1+ from unittest .mock import AsyncMock , MagicMock , patch
22
33import pytest
44
@@ -24,35 +24,49 @@ def account():
2424 )
2525
2626
27- @patch ("dbt_mcp.project.project_resolver.requests.get" )
28- def test_get_all_projects_for_account_paginates (mock_get : Mock , base_headers , account ):
27+ def create_mock_response (data : dict ) -> MagicMock :
28+ resp = MagicMock ()
29+ resp .json .return_value = data
30+ resp .raise_for_status .return_value = None
31+ return resp
32+
33+
34+ def create_mock_httpx_client (responses : list ) -> AsyncMock :
35+ mock_client = AsyncMock ()
36+ mock_client .get = AsyncMock (side_effect = responses )
37+ mock_client .__aenter__ = AsyncMock (return_value = mock_client )
38+ mock_client .__aexit__ = AsyncMock (return_value = None )
39+ return mock_client
40+
41+
42+ async def test_get_all_projects_for_account_paginates (base_headers , account ):
2943 # Two pages: first full page (limit=2), second partial page (1 item) -> stop
30- first_page_resp = Mock ()
31- first_page_resp .json .return_value = {
32- "data" : [
33- {"id" : 101 , "name" : "Proj A" , "account_id" : account .id },
34- {"id" : 102 , "name" : "Proj B" , "account_id" : account .id },
35- ]
36- }
37- first_page_resp .raise_for_status .return_value = None
38-
39- second_page_resp = Mock ()
40- second_page_resp .json .return_value = {
41- "data" : [
42- {"id" : 103 , "name" : "Proj C" , "account_id" : account .id },
43- ]
44- }
45- second_page_resp .raise_for_status .return_value = None
46-
47- mock_get .side_effect = [first_page_resp , second_page_resp ]
48-
49- result = get_all_projects_for_account (
50- dbt_platform_url = "https://cloud.getdbt.com" ,
51- account = account ,
52- headers = base_headers ,
53- page_size = 2 ,
44+ first_page_resp = create_mock_response (
45+ {
46+ "data" : [
47+ {"id" : 101 , "name" : "Proj A" , "account_id" : account .id },
48+ {"id" : 102 , "name" : "Proj B" , "account_id" : account .id },
49+ ]
50+ }
51+ )
52+ second_page_resp = create_mock_response (
53+ {
54+ "data" : [
55+ {"id" : 103 , "name" : "Proj C" , "account_id" : account .id },
56+ ]
57+ }
5458 )
5559
60+ mock_client = create_mock_httpx_client ([first_page_resp , second_page_resp ])
61+
62+ with patch ("httpx.AsyncClient" , return_value = mock_client ):
63+ result = await get_all_projects_for_account (
64+ dbt_platform_url = "https://cloud.getdbt.com" ,
65+ account = account ,
66+ headers = base_headers ,
67+ page_size = 2 ,
68+ )
69+
5670 # Should aggregate 3 projects and include account_name field
5771 assert len (result ) == 3
5872 assert {p .id for p in result } == {101 , 102 , 103 }
@@ -63,52 +77,45 @@ def test_get_all_projects_for_account_paginates(mock_get: Mock, base_headers, ac
6377 "https://cloud.getdbt.com/api/v3/accounts/1/projects/?state=1&offset=0&limit=2" ,
6478 "https://cloud.getdbt.com/api/v3/accounts/1/projects/?state=1&offset=2&limit=2" ,
6579 ]
66- actual_urls = [
67- call .kwargs ["url" ] if "url" in call .kwargs else call .args [0 ]
68- for call in mock_get .call_args_list
69- ]
80+ actual_urls = [call .args [0 ] for call in mock_client .get .call_args_list ]
7081 assert actual_urls == expected_urls
7182
7283
73- @patch ("dbt_mcp.project.environment_resolver.requests.get" )
74- def test_get_all_environments_for_project_paginates (mock_get : Mock , base_headers ):
84+ async def test_get_all_environments_for_project_paginates (base_headers ):
7585 # Two pages: first full page (limit=2), second partial (1 item)
76- first_page_resp = Mock ()
77- first_page_resp .json .return_value = {
78- "data" : [
79- {"id" : 201 , "name" : "Dev" , "deployment_type" : "development" },
80- {"id" : 202 , "name" : "Prod" , "deployment_type" : "production" },
81- ]
82- }
83- first_page_resp .raise_for_status .return_value = None
84-
85- second_page_resp = Mock ()
86- second_page_resp .json .return_value = {
87- "data" : [
88- {"id" : 203 , "name" : "Staging" , "deployment_type" : "development" },
89- ]
90- }
91- second_page_resp .raise_for_status .return_value = None
92-
93- mock_get .side_effect = [first_page_resp , second_page_resp ]
94-
95- result = _get_all_environments_for_project (
96- dbt_platform_url = "https://cloud.getdbt.com" ,
97- account_id = 1 ,
98- project_id = 9 ,
99- headers = base_headers ,
100- page_size = 2 ,
86+ first_page_resp = create_mock_response (
87+ {
88+ "data" : [
89+ {"id" : 201 , "name" : "Dev" , "deployment_type" : "development" },
90+ {"id" : 202 , "name" : "Prod" , "deployment_type" : "production" },
91+ ]
92+ }
93+ )
94+ second_page_resp = create_mock_response (
95+ {
96+ "data" : [
97+ {"id" : 203 , "name" : "Staging" , "deployment_type" : "development" },
98+ ]
99+ }
101100 )
102101
102+ mock_client = create_mock_httpx_client ([first_page_resp , second_page_resp ])
103+
104+ with patch ("httpx.AsyncClient" , return_value = mock_client ):
105+ result = await _get_all_environments_for_project (
106+ dbt_platform_url = "https://cloud.getdbt.com" ,
107+ account_id = 1 ,
108+ project_id = 9 ,
109+ headers = base_headers ,
110+ page_size = 2 ,
111+ )
112+
103113 assert len (result ) == 3
104114 assert {e .id for e in result } == {201 , 202 , 203 }
105115
106116 expected_urls = [
107117 "https://cloud.getdbt.com/api/v3/accounts/1/projects/9/environments/?state=1&offset=0&limit=2" ,
108118 "https://cloud.getdbt.com/api/v3/accounts/1/projects/9/environments/?state=1&offset=2&limit=2" ,
109119 ]
110- actual_urls = [
111- call .kwargs ["url" ] if "url" in call .kwargs else call .args [0 ]
112- for call in mock_get .call_args_list
113- ]
120+ actual_urls = [call .args [0 ] for call in mock_client .get .call_args_list ]
114121 assert actual_urls == expected_urls
0 commit comments