88import sys
99from typing import cast , Dict
1010import unittest
11+ import pytest_httpserver
12+ import pytest
1113
1214sys .path .append (".." )
13-
14- # httpretty currently doesn't work, but mocket with the compat interface
15- # does.
16- from mocket import Mocket # type: ignore
17- from mocket .plugins .httpretty import httpretty , httprettified # type: ignore
1815import geoip2
1916from geoip2 .errors import (
2017 AddressNotFoundError ,
2926
3027
3128class TestBaseClient (unittest .TestCase ):
32- base_uri = "https://geoip.maxmind.com/geoip/v2.1/"
3329 country = {
3430 "continent" : {"code" : "NA" , "geoname_id" : 42 , "names" : {"en" : "North America" }},
3531 "country" : {
@@ -64,12 +60,13 @@ def _content_type(self, endpoint):
6460 + "+json; charset=UTF-8; version=1.0"
6561 )
6662
67- @httprettified
63+ @pytest .fixture (autouse = True )
64+ def setup_httpserver (self , httpserver : pytest_httpserver .HTTPServer ):
65+ self .httpserver = httpserver
66+
6867 def test_country_ok (self ):
69- httpretty .register_uri (
70- httpretty .GET ,
71- self .base_uri + "country/1.2.3.4" ,
72- body = json .dumps (self .country ),
68+ self .httpserver .expect_request ("/geoip/v2.1/country/1.2.3.4" ).respond_with_json (
69+ self .country ,
7370 status = 200 ,
7471 content_type = self ._content_type ("country" ),
7572 )
@@ -111,12 +108,9 @@ def test_country_ok(self):
111108 self .assertTrue (country .traits .is_anycast )
112109 self .assertEqual (country .raw , self .country , "raw response is correct" )
113110
114- @httprettified
115111 def test_me (self ):
116- httpretty .register_uri (
117- httpretty .GET ,
118- self .base_uri + "country/me" ,
119- body = json .dumps (self .country ),
112+ self .httpserver .expect_request ("/geoip/v2.1/country/me" ).respond_with_json (
113+ self .country ,
120114 status = 200 ,
121115 content_type = self ._content_type ("country" ),
122116 )
@@ -131,33 +125,29 @@ def test_me(self):
131125 "country('me') returns Country object" ,
132126 )
133127
134- @httprettified
135128 def test_200_error (self ):
136- httpretty .register_uri (
137- httpretty .GET ,
138- self .base_uri + "country/1.1.1.1" ,
139- body = "" ,
129+ self .httpserver .expect_request ("/geoip/v2.1/country/1.1.1.1" ).respond_with_data (
130+ "" ,
140131 status = 200 ,
141132 content_type = self ._content_type ("country" ),
142133 )
134+
143135 with self .assertRaisesRegex (
144136 GeoIP2Error , "could not decode the response as JSON"
145137 ):
146138 self .run_client (self .client .country ("1.1.1.1" ))
147139
148- @httprettified
149140 def test_bad_ip_address (self ):
150141 with self .assertRaisesRegex (
151142 ValueError , "'1.2.3' does not appear to be an IPv4 " "or IPv6 address"
152143 ):
153144 self .run_client (self .client .country ("1.2.3" ))
154145
155- @httprettified
156146 def test_no_body_error (self ):
157- httpretty . register_uri (
158- httpretty . GET ,
159- self . base_uri + "country/" + "1.2.3.7" ,
160- body = "" ,
147+ self . httpserver . expect_request (
148+ "/geoip/v2.1/country/" + "1.2.3.7"
149+ ). respond_with_data (
150+ "" ,
161151 status = 400 ,
162152 content_type = self ._content_type ("country" ),
163153 )
@@ -166,27 +156,28 @@ def test_no_body_error(self):
166156 ):
167157 self .run_client (self .client .country ("1.2.3.7" ))
168158
169- @httprettified
170159 def test_weird_body_error (self ):
171- httpretty .register_uri (
172- httpretty .GET ,
173- self .base_uri + "country/" + "1.2.3.8" ,
174- body = '{"wierd": 42}' ,
160+
161+ self .httpserver .expect_request (
162+ "/geoip/v2.1/country/" + "1.2.3.8"
163+ ).respond_with_json (
164+ {"wierd" : 42 },
175165 status = 400 ,
176166 content_type = self ._content_type ("country" ),
177167 )
168+
178169 with self .assertRaisesRegex (
179170 HTTPError ,
180171 "Response contains JSON but it does not " "specify code or error keys" ,
181172 ):
182173 self .run_client (self .client .country ("1.2.3.8" ))
183174
184- @httprettified
185175 def test_bad_body_error (self ):
186- httpretty .register_uri (
187- httpretty .GET ,
188- self .base_uri + "country/" + "1.2.3.9" ,
189- body = "bad body" ,
176+
177+ self .httpserver .expect_request (
178+ "/geoip/v2.1/country/" + "1.2.3.9"
179+ ).respond_with_data (
180+ "bad body" ,
190181 status = 400 ,
191182 content_type = self ._content_type ("country" ),
192183 )
@@ -195,19 +186,23 @@ def test_bad_body_error(self):
195186 ):
196187 self .run_client (self .client .country ("1.2.3.9" ))
197188
198- @httprettified
199189 def test_500_error (self ):
200- httpretty .register_uri (
201- httpretty .GET , self .base_uri + "country/" + "1.2.3.10" , status = 500
190+ self .httpserver .expect_request (
191+ "/geoip/v2.1/country/" + "1.2.3.10"
192+ ).respond_with_data (
193+ "" ,
194+ status = 500 ,
195+ content_type = self ._content_type ("country" ),
202196 )
203197 with self .assertRaisesRegex (HTTPError , r"Received a server error \(500\) for" ):
204198 self .run_client (self .client .country ("1.2.3.10" ))
205199
206- @httprettified
207200 def test_300_error (self ):
208- httpretty .register_uri (
209- httpretty .GET ,
210- self .base_uri + "country/" + "1.2.3.11" ,
201+
202+ self .httpserver .expect_request (
203+ "/geoip/v2.1/country/" + "1.2.3.11"
204+ ).respond_with_data (
205+ "" ,
211206 status = 300 ,
212207 content_type = self ._content_type ("country" ),
213208 )
@@ -216,96 +211,86 @@ def test_300_error(self):
216211 ):
217212 self .run_client (self .client .country ("1.2.3.11" ))
218213
219- @httprettified
220214 def test_ip_address_required (self ):
221215 self ._test_error (400 , "IP_ADDRESS_REQUIRED" , InvalidRequestError )
222216
223- @httprettified
224217 def test_ip_address_not_found (self ):
225218 self ._test_error (404 , "IP_ADDRESS_NOT_FOUND" , AddressNotFoundError )
226219
227- @httprettified
228220 def test_ip_address_reserved (self ):
229221 self ._test_error (400 , "IP_ADDRESS_RESERVED" , AddressNotFoundError )
230222
231- @httprettified
232223 def test_permission_required (self ):
233224 self ._test_error (403 , "PERMISSION_REQUIRED" , PermissionRequiredError )
234225
235- @httprettified
236226 def test_auth_invalid (self ):
237227 self ._test_error (400 , "AUTHORIZATION_INVALID" , AuthenticationError )
238228
239- @httprettified
240229 def test_license_key_required (self ):
241230 self ._test_error (401 , "LICENSE_KEY_REQUIRED" , AuthenticationError )
242231
243- @httprettified
244232 def test_account_id_required (self ):
245233 self ._test_error (401 , "ACCOUNT_ID_REQUIRED" , AuthenticationError )
246234
247- @httprettified
248235 def test_user_id_required (self ):
249236 self ._test_error (401 , "USER_ID_REQUIRED" , AuthenticationError )
250237
251- @httprettified
252238 def test_account_id_unkown (self ):
253239 self ._test_error (401 , "ACCOUNT_ID_UNKNOWN" , AuthenticationError )
254240
255- @httprettified
256241 def test_user_id_unkown (self ):
257242 self ._test_error (401 , "USER_ID_UNKNOWN" , AuthenticationError )
258243
259- @httprettified
260244 def test_out_of_queries_error (self ):
261245 self ._test_error (402 , "OUT_OF_QUERIES" , OutOfQueriesError )
262246
263247 def _test_error (self , status , error_code , error_class ):
264248 msg = "Some error message"
265249 body = {"error" : msg , "code" : error_code }
266- httpretty . register_uri (
267- httpretty . GET ,
268- self . base_uri + "country/1.2.3.18" ,
269- body = json . dumps ( body ) ,
250+ self . httpserver . expect_request (
251+ "/geoip/v2.1/country/" + "1.2.3.18"
252+ ). respond_with_json (
253+ body ,
270254 status = status ,
271255 content_type = self ._content_type ("country" ),
272256 )
273257 with self .assertRaisesRegex (error_class , msg ):
274258 self .run_client (self .client .country ("1.2.3.18" ))
275259
276- @httprettified
277260 def test_unknown_error (self ):
278261 msg = "Unknown error type"
279262 ip = "1.2.3.19"
280263 body = {"error" : msg , "code" : "UNKNOWN_TYPE" }
281- httpretty .register_uri (
282- httpretty .GET ,
283- self .base_uri + "country/" + ip ,
284- body = json .dumps (body ),
264+ self .httpserver .expect_request ("/geoip/v2.1/country/" + ip ).respond_with_json (
265+ body ,
285266 status = 400 ,
286267 content_type = self ._content_type ("country" ),
287268 )
288269 with self .assertRaisesRegex (InvalidRequestError , msg ):
289270 self .run_client (self .client .country (ip ))
290271
291- @httprettified
292272 def test_request (self ):
293- httpretty .register_uri (
294- httpretty .GET ,
295- self .base_uri + "country/" + "1.2.3.4" ,
296- body = json .dumps (self .country ),
297- status = 200 ,
298- content_type = self ._content_type ("country" ),
299- )
300- self .run_client (self .client .country ("1.2.3.4" ))
301- request = httpretty .last_request
273+
274+ request = None
275+
276+ def custom_handler (r ):
277+ nonlocal request
278+ request = r
279+ return ""
280+
281+ self .httpserver .expect_request (
282+ "/geoip/v2.1/country/" + "1.2.3.4"
283+ ).respond_with_handler (custom_handler )
284+ try :
285+ self .run_client (self .client .country ("1.2.3.4" ))
286+ except Exception as e :
287+ # just to avoid the exception
288+ pass
302289
303290 self .assertEqual (
304291 request .path , "/geoip/v2.1/country/1.2.3.4" , "correct URI is used"
305292 )
306293
307- # This is to prevent breakage if header normalization in Mocket
308- # changes again in the future.
309294 headers = {k .lower (): v for k , v in request .headers .items ()}
310295 self .assertEqual (headers ["accept" ], "application/json" , "correct Accept header" )
311296 self .assertRegex (
@@ -319,12 +304,9 @@ def test_request(self):
319304 "correct auth" ,
320305 )
321306
322- @httprettified
323307 def test_city_ok (self ):
324- httpretty .register_uri (
325- httpretty .GET ,
326- self .base_uri + "city/" + "1.2.3.4" ,
327- body = json .dumps (self .country ),
308+ self .httpserver .expect_request ("/geoip/v2.1/city/1.2.3.4" ).respond_with_json (
309+ self .country ,
328310 status = 200 ,
329311 content_type = self ._content_type ("city" ),
330312 )
@@ -335,14 +317,13 @@ def test_city_ok(self):
335317 )
336318 self .assertTrue (city .traits .is_anycast )
337319
338- @httprettified
339320 def test_insights_ok (self ):
340- httpretty . register_uri (
341- httpretty . GET ,
342- self . base_uri + "insights/1.2.3.4" ,
343- body = json . dumps ( self .insights ) ,
321+ self . httpserver . expect_request (
322+ "/geoip/v2.1/insights/" + "1.2.3.4"
323+ ). respond_with_json (
324+ self .insights ,
344325 status = 200 ,
345- content_type = self ._content_type ("country " ),
326+ content_type = self ._content_type ("insights " ),
346327 )
347328 insights = self .run_client (self .client .insights ("1.2.3.4" ))
348329 self .assertEqual (
@@ -374,6 +355,7 @@ class TestClient(TestBaseClient):
374355 def setUp (self ):
375356 self .client_class = Client
376357 self .client = Client (42 , "abcdef123456" )
358+ self .client ._base_uri = self .httpserver .url_for ("/" ) + "geoip/v2.1"
377359
378360 def run_client (self , v ):
379361 return v
@@ -384,6 +366,7 @@ def setUp(self):
384366 self ._loop = asyncio .new_event_loop ()
385367 self .client_class = AsyncClient
386368 self .client = AsyncClient (42 , "abcdef123456" )
369+ self .client ._base_uri = self .httpserver .url_for ("/" ) + "geoip/v2.1"
387370
388371 def tearDown (self ):
389372 self ._loop .run_until_complete (self .client .close ())
0 commit comments