11import unittest
22from unittest .mock import patch
3+
34import httpx
5+
46from keboola .http_client import AsyncHttpClient
57
68
@@ -15,7 +17,7 @@ async def test_get(self):
1517
1618 client = AsyncHttpClient (self .base_url , retries = self .retries )
1719
18- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
20+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as mock_request :
1921 response = await client .get ("/endpoint" )
2022 self .assertEqual (response , expected_response )
2123 mock_request .assert_called_once_with ("GET" , url = "https://api.example.com/endpoint" )
@@ -27,11 +29,12 @@ async def test_post(self):
2729
2830 client = AsyncHttpClient (self .base_url , retries = self .retries )
2931
30- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
32+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as mock_request :
3133 response = await client .post ("/endpoint" , json = {"data" : "example" })
3234 self .assertEqual (response , expected_response )
33- mock_request .assert_called_once_with ("POST" , url = "https://api.example.com/endpoint" ,
34- json = {"data" : "example" })
35+ mock_request .assert_called_once_with (
36+ "POST" , url = "https://api.example.com/endpoint" , json = {"data" : "example" }
37+ )
3538
3639 async def test_handle_success_response (self ):
3740 expected_response = {"message" : "Success" }
@@ -40,7 +43,7 @@ async def test_handle_success_response(self):
4043
4144 client = AsyncHttpClient (self .base_url , retries = self .retries )
4245
43- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
46+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as mock_request :
4447 response = await client .get ("/endpoint" )
4548 self .assertEqual (response , expected_response )
4649 mock_request .assert_called_once_with ("GET" , url = "https://api.example.com/endpoint" )
@@ -51,7 +54,7 @@ async def test_handle_client_error_response(self):
5154
5255 client = AsyncHttpClient (self .base_url , retries = self .retries , retry_status_codes = [404 ])
5356
54- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
57+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as mock_request :
5558 with self .assertRaises (httpx .HTTPStatusError ):
5659 await client .get ("/endpoint" )
5760
@@ -65,15 +68,15 @@ async def test_handle_server_error_response(self):
6568
6669 client = AsyncHttpClient (self .base_url , retries = self .retries , retry_status_codes = [500 ])
6770
68- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
71+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as mock_request :
6972 with self .assertRaises (httpx .HTTPStatusError ):
7073 await client .get ("/endpoint" )
7174
7275 assert mock_request .call_count == self .retries + 1
7376
7477 mock_request .assert_called_with ("GET" , url = "https://api.example.com/endpoint" )
7578
76- @patch .object (httpx .AsyncClient , ' request' )
79+ @patch .object (httpx .AsyncClient , " request" )
7780 async def test_post_raw_default_pars_with_none_custom_pars_passes (self , mock_request ):
7881 url = f"{ self .base_url } /endpoint"
7982 test_def_par = {"default_par" : "test" }
@@ -84,7 +87,7 @@ async def test_post_raw_default_pars_with_none_custom_pars_passes(self, mock_req
8487
8588 mock_request .assert_called_once_with ("POST" , url = url , params = test_def_par )
8689
87- @patch .object (httpx .AsyncClient , ' request' )
90+ @patch .object (httpx .AsyncClient , " request" )
8891 async def test_post_default_pars_with_none_custom_pars_passes (self , mock_request ):
8992 url = f"{ self .base_url } /endpoint"
9093 test_def_par = {"default_par" : "test" }
@@ -95,7 +98,7 @@ async def test_post_default_pars_with_none_custom_pars_passes(self, mock_request
9598
9699 mock_request .assert_called_once_with ("POST" , url = url , params = test_def_par )
97100
98- @patch .object (httpx .AsyncClient , ' request' )
101+ @patch .object (httpx .AsyncClient , " request" )
99102 async def test_post_raw_default_pars_with_custom_pars_passes (self , mock_request ):
100103 url = f"{ self .base_url } /endpoint"
101104 test_def_par = {"default_par" : "test" }
@@ -108,7 +111,7 @@ async def test_post_raw_default_pars_with_custom_pars_passes(self, mock_request)
108111 test_cust_def_par = {** test_def_par , ** cust_par }
109112 mock_request .assert_called_once_with ("POST" , url = url , params = test_cust_def_par )
110113
111- @patch .object (httpx .AsyncClient , ' request' )
114+ @patch .object (httpx .AsyncClient , " request" )
112115 async def test_post_default_pars_with_custom_pars_passes (self , mock_request ):
113116 url = f"{ self .base_url } /endpoint"
114117 test_def_par = {"default_par" : "test" }
@@ -121,7 +124,7 @@ async def test_post_default_pars_with_custom_pars_passes(self, mock_request):
121124 test_cust_def_par = {** test_def_par , ** cust_par }
122125 mock_request .assert_called_once_with ("POST" , url = url , params = test_cust_def_par )
123126
124- @patch .object (httpx .AsyncClient , ' request' )
127+ @patch .object (httpx .AsyncClient , " request" )
125128 async def test_post_raw_default_pars_with_custom_pars_to_None_passes (self , mock_request ):
126129 url = f"{ self .base_url } /endpoint"
127130 test_def_par = {"default_par" : "test" }
@@ -136,7 +139,7 @@ async def test_post_raw_default_pars_with_custom_pars_to_None_passes(self, mock_
136139 test_cust_def_par = {** test_def_par , ** _cust_par_transformed }
137140 mock_request .assert_called_once_with ("POST" , url = url , params = test_cust_def_par )
138141
139- @patch .object (httpx .AsyncClient , ' request' )
142+ @patch .object (httpx .AsyncClient , " request" )
140143 async def test_post_default_pars_with_custom_pars_to_None_passes (self , mock_request ):
141144 url = f"{ self .base_url } /endpoint"
142145 test_def_par = {"default_par" : "test" }
@@ -151,146 +154,162 @@ async def test_post_default_pars_with_custom_pars_to_None_passes(self, mock_requ
151154 test_cust_def_par = {** test_def_par , ** _cust_par_transformed }
152155 mock_request .assert_called_once_with ("POST" , url = url , params = test_cust_def_par )
153156
154- @patch .object (httpx .AsyncClient , ' request' )
157+ @patch .object (httpx .AsyncClient , " request" )
155158 async def test_all_methods_requests_raw_with_custom_pars_passes (self , mock_request ):
156159 client = AsyncHttpClient (self .base_url )
157160
158161 cust_par = {"custom_par" : "custom_par_value" }
159162
160163 for m in client .ALLOWED_METHODS :
161164 await client ._request (m , ignore_auth = False , params = cust_par )
162- mock_request .assert_called_with (m , url = self .base_url + "/" , params = cust_par )
165+ mock_request .assert_called_with (m , url = self .base_url + "/" , params = cust_par )
163166
164- @patch .object (httpx .AsyncClient , ' request' )
167+ @patch .object (httpx .AsyncClient , " request" )
165168 async def test_all_methods_skip_auth (self , mock_request ):
166169 client = AsyncHttpClient (self .base_url , auth = ("my_user" , "password123" ))
167170
168- for m in [' GET' , ' POST' , ' PATCH' , ' UPDATE' , ' PUT' , ' DELETE' ]:
171+ for m in [" GET" , " POST" , " PATCH" , " UPDATE" , " PUT" , " DELETE" ]:
169172 await client ._request (m , ignore_auth = True )
170- mock_request .assert_called_with (m , url = self .base_url + "/" )
173+ mock_request .assert_called_with (m , url = self .base_url + "/" )
171174
172- @patch .object (httpx .AsyncClient , ' request' )
175+ @patch .object (httpx .AsyncClient , " request" )
173176 async def test_request_skip_auth_header (self , mock_request ):
174177 def_header = {"def_header" : "test" }
175- client = AsyncHttpClient ('http://example.com' , default_headers = def_header ,
176- auth_header = {"Authorization" : "test" })
178+ client = AsyncHttpClient (
179+ "http://example.com" , default_headers = def_header , auth_header = {"Authorization" : "test" }
180+ )
177181
178- await client ._request (' POST' , ' abc' , ignore_auth = True )
179- mock_request .assert_called_with (' POST' , url = "http://example.com/abc" , headers = def_header )
182+ await client ._request (" POST" , " abc" , ignore_auth = True )
183+ mock_request .assert_called_with (" POST" , url = "http://example.com/abc" , headers = def_header )
180184
181- @patch .object (httpx .AsyncClient , ' request' )
185+ @patch .object (httpx .AsyncClient , " request" )
182186 async def test_request_auth (self , mock_request ):
183187 def_header = {"def_header" : "test" }
184188 auth = ("my_user" , "password123" )
185189 client = AsyncHttpClient (self .base_url , auth = auth , default_headers = def_header )
186190
187- await client ._request ('POST' , 'abc' )
188- mock_request .assert_called_with ('POST' , url = self .base_url + "/abc" , headers = def_header ,
189- auth = auth )
191+ await client ._request ("POST" , "abc" )
192+ mock_request .assert_called_with ("POST" , url = self .base_url + "/abc" , headers = def_header , auth = auth )
190193
191- @patch .object (httpx .AsyncClient , ' request' )
194+ @patch .object (httpx .AsyncClient , " request" )
192195 async def test_all_methods (self , mock_request ):
193- client = AsyncHttpClient (self .base_url , default_headers = {'header1' : 'headerval' },
194- auth_header = {'api_token' : 'abdc1234' })
196+ client = AsyncHttpClient (
197+ self .base_url , default_headers = {"header1" : "headerval" }, auth_header = {"api_token" : "abdc1234" }
198+ )
195199
196- target_url = f' { self .base_url } /abc'
200+ target_url = f" { self .base_url } /abc"
197201
198202 for m in client .ALLOWED_METHODS :
199- await client ._request (m , 'abc' , params = {'exclude' : 'componentDetails' }, headers = {'abc' : '123' },
200- data = {'attr1' : 'val1' })
201- mock_request .assert_called_with (m , url = target_url ,
202- params = {'exclude' : 'componentDetails' },
203- headers = {'api_token' : 'abdc1234' , 'header1' : 'headerval' , 'abc' : '123' },
204- data = {'attr1' : 'val1' })
205-
206- @patch .object (httpx .AsyncClient , 'request' )
203+ await client ._request (
204+ m , "abc" , params = {"exclude" : "componentDetails" }, headers = {"abc" : "123" }, data = {"attr1" : "val1" }
205+ )
206+ mock_request .assert_called_with (
207+ m ,
208+ url = target_url ,
209+ params = {"exclude" : "componentDetails" },
210+ headers = {"api_token" : "abdc1234" , "header1" : "headerval" , "abc" : "123" },
211+ data = {"attr1" : "val1" },
212+ )
213+
214+ @patch .object (httpx .AsyncClient , "request" )
207215 async def test_all_methods_requests_raw_with_is_absolute_path_true (self , mock_request ):
208216 def_header = {"def_header" : "test" }
209217 client = AsyncHttpClient (self .base_url , default_headers = def_header )
210218
211219 for m in client .ALLOWED_METHODS :
212- await client ._request (m , ' http://example2.com/v1/' , is_absolute_path = True )
213- mock_request .assert_called_with (m , url = ' http://example2.com/v1/' , headers = def_header )
220+ await client ._request (m , " http://example2.com/v1/" , is_absolute_path = True )
221+ mock_request .assert_called_with (m , url = " http://example2.com/v1/" , headers = def_header )
214222
215- @patch .object (httpx .AsyncClient , ' request' )
223+ @patch .object (httpx .AsyncClient , " request" )
216224 async def test_all_methods_requests_raw_with_is_absolute_path_false (self , mock_request ):
217225 def_header = {"def_header" : "test" }
218226 client = AsyncHttpClient (self .base_url , default_headers = def_header )
219227
220228 for m in client .ALLOWED_METHODS :
221- await client ._request (m , ' cars' )
222- mock_request .assert_called_with (m , url = self .base_url + "/cars" , headers = def_header )
229+ await client ._request (m , " cars" )
230+ mock_request .assert_called_with (m , url = self .base_url + "/cars" , headers = def_header )
223231
224- @patch .object (httpx .AsyncClient , ' request' )
232+ @patch .object (httpx .AsyncClient , " request" )
225233 async def test_all_methods_kwargs (self , mock_request ):
226234 client = AsyncHttpClient (self .base_url )
227235
228236 for m in client .ALLOWED_METHODS :
229- await client ._request (m , 'cars' , data = {'data' : '123' }, cert = '/path/to/cert' , files = {'a' : '/path/to/file' },
230- params = {'par1' : 'val1' })
231-
232- mock_request .assert_called_with (m , url = self .base_url + "/cars" , data = {'data' : '123' },
233- cert = '/path/to/cert' , files = {'a' : '/path/to/file' },
234- params = {'par1' : 'val1' })
237+ await client ._request (
238+ m ,
239+ "cars" ,
240+ data = {"data" : "123" },
241+ cert = "/path/to/cert" ,
242+ files = {"a" : "/path/to/file" },
243+ params = {"par1" : "val1" },
244+ )
245+
246+ mock_request .assert_called_with (
247+ m ,
248+ url = self .base_url + "/cars" ,
249+ data = {"data" : "123" },
250+ cert = "/path/to/cert" ,
251+ files = {"a" : "/path/to/file" },
252+ params = {"par1" : "val1" },
253+ )
235254
236255 async def test_build_url_rel_path (self ):
237- url = ' https://example.com/'
256+ url = " https://example.com/"
238257 cl = AsyncHttpClient (url )
239- expected_url = ' https://example.com/storage'
240- actual_url = await cl ._build_url (' storage' )
258+ expected_url = " https://example.com/storage"
259+ actual_url = await cl ._build_url (" storage" )
241260 self .assertEqual (expected_url , actual_url )
242261
243262 async def test_build_url_abs_path (self ):
244- url = ' https://example.com/'
263+ url = " https://example.com/"
245264 cl = AsyncHttpClient (url )
246- expected_url = ' https://example2.com/storage'
247- actual_url = await cl ._build_url (' https://example2.com/storage' , True )
265+ expected_url = " https://example2.com/storage"
266+ actual_url = await cl ._build_url (" https://example2.com/storage" , True )
248267 self .assertEqual (expected_url , actual_url )
249268
250269 async def test_build_url_empty_endpoint_path_leads_to_base_url (self ):
251- url = ' https://example.com/'
270+ url = " https://example.com/"
252271 cl = AsyncHttpClient (url )
253272 expected_url = url
254273
255274 actual_url = await cl ._build_url ()
256275 self .assertEqual (expected_url , actual_url )
257276
258- actual_url = await cl ._build_url ('' )
277+ actual_url = await cl ._build_url ("" )
259278 self .assertEqual (expected_url , actual_url )
260279
261280 actual_url = await cl ._build_url (None )
262281 self .assertEqual (expected_url , actual_url )
263282
264- actual_url = await cl ._build_url ('' , is_absolute_path = True )
283+ actual_url = await cl ._build_url ("" , is_absolute_path = True )
265284 self .assertEqual (expected_url , actual_url )
266285
267286 actual_url = await cl ._build_url (None , is_absolute_path = True )
268287 self .assertEqual (expected_url , actual_url )
269288
270289 async def test_build_url_base_url_appends_slash (self ):
271- url = ' https://example.com'
290+ url = " https://example.com"
272291 cl = AsyncHttpClient (url )
273- expected_base_url = ' https://example.com/'
292+ expected_base_url = " https://example.com/"
274293
275294 self .assertEqual (expected_base_url , cl .base_url )
276295
277296 async def test_update_auth_header_None (self ):
278297 existing_header = None
279- new_header = {' api_token' : ' token_value' }
298+ new_header = {" api_token" : " token_value" }
280299
281- cl = AsyncHttpClient (' https://example.com' , auth_header = existing_header )
300+ cl = AsyncHttpClient (" https://example.com" , auth_header = existing_header )
282301 await cl .update_auth_header (new_header , overwrite = False )
283302 self .assertDictEqual (cl ._auth_header , new_header )
284303
285- new_header_2 = {' password' : ' 123' }
304+ new_header_2 = {" password" : " 123" }
286305 await cl .update_auth_header (new_header_2 , overwrite = True )
287306 self .assertDictEqual (cl ._auth_header , new_header_2 )
288307
289308 async def test_update_existing_auth_header (self ):
290- existing_header = {' authorization' : ' value' }
291- new_header = {' api_token' : ' token_value' }
309+ existing_header = {" authorization" : " value" }
310+ new_header = {" api_token" : " token_value" }
292311
293- cl = AsyncHttpClient (' https://example.com' , auth_header = existing_header )
312+ cl = AsyncHttpClient (" https://example.com" , auth_header = existing_header )
294313 await cl .update_auth_header (new_header , overwrite = False )
295314 self .assertDictEqual (cl ._auth_header , {** existing_header , ** new_header })
296315
@@ -300,11 +319,12 @@ async def test_detailed_exception(self):
300319
301320 client = AsyncHttpClient (self .base_url )
302321
303- with patch .object (httpx .AsyncClient , ' request' , return_value = mock_response ) as mock_request :
322+ with patch .object (httpx .AsyncClient , " request" , return_value = mock_response ) as _ :
304323 with self .assertRaises (httpx .HTTPStatusError ) as e :
305324 await client .get ("/endpoint" )
306325
307326 assert "Client error '404 Not Found' for url 'https://api.example.com/endpoint'" in str (e .exception )
308327
328+
309329if __name__ == "__main__" :
310330 unittest .main ()
0 commit comments