8
8
import sys
9
9
from typing import cast , Dict
10
10
import unittest
11
+ import requests
12
+ import pytest_httpserver
13
+ import pytest
11
14
12
15
sys .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
18
16
import geoip2
19
17
from geoip2 .errors import (
20
18
AddressNotFoundError ,
29
27
30
28
31
29
class TestBaseClient (unittest .TestCase ):
32
- base_uri = "https://geoip.maxmind.com/geoip/v2.1/"
30
+ # base_uri = "https://geoip.maxmind.com/geoip/v2.1/"
33
31
country = {
34
32
"continent" : {"code" : "NA" , "geoname_id" : 42 , "names" : {"en" : "North America" }},
35
33
"country" : {
@@ -64,12 +62,13 @@ def _content_type(self, endpoint):
64
62
+ "+json; charset=UTF-8; version=1.0"
65
63
)
66
64
67
- @httprettified
65
+ @pytest .fixture (autouse = True )
66
+ def setup_httpserver (self , httpserver : pytest_httpserver .HTTPServer ):
67
+ self .httpserver = httpserver
68
+
68
69
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 ),
70
+ self .httpserver .expect_request ("/geoip/v2.1/country/1.2.3.4" ).respond_with_json (
71
+ self .country ,
73
72
status = 200 ,
74
73
content_type = self ._content_type ("country" ),
75
74
)
@@ -111,12 +110,9 @@ def test_country_ok(self):
111
110
self .assertTrue (country .traits .is_anycast )
112
111
self .assertEqual (country .raw , self .country , "raw response is correct" )
113
112
114
- @httprettified
115
113
def test_me (self ):
116
- httpretty .register_uri (
117
- httpretty .GET ,
118
- self .base_uri + "country/me" ,
119
- body = json .dumps (self .country ),
114
+ self .httpserver .expect_request ("/geoip/v2.1/country/me" ).respond_with_json (
115
+ self .country ,
120
116
status = 200 ,
121
117
content_type = self ._content_type ("country" ),
122
118
)
@@ -131,33 +127,27 @@ def test_me(self):
131
127
"country('me') returns Country object" ,
132
128
)
133
129
134
- @httprettified
135
130
def test_200_error (self ):
136
- httpretty .register_uri (
137
- httpretty .GET ,
138
- self .base_uri + "country/1.1.1.1" ,
139
- body = "" ,
131
+ self .httpserver .expect_request ("/geoip/v2.1/country/1.1.1.1" ).respond_with_data (
132
+ "" ,
140
133
status = 200 ,
141
134
content_type = self ._content_type ("country" ),
142
135
)
136
+
143
137
with self .assertRaisesRegex (
144
138
GeoIP2Error , "could not decode the response as JSON"
145
139
):
146
140
self .run_client (self .client .country ("1.1.1.1" ))
147
141
148
- @httprettified
149
142
def test_bad_ip_address (self ):
150
143
with self .assertRaisesRegex (
151
144
ValueError , "'1.2.3' does not appear to be an IPv4 " "or IPv6 address"
152
145
):
153
146
self .run_client (self .client .country ("1.2.3" ))
154
147
155
- @httprettified
156
148
def test_no_body_error (self ):
157
- httpretty .register_uri (
158
- httpretty .GET ,
159
- self .base_uri + "country/" + "1.2.3.7" ,
160
- body = "" ,
149
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + "1.2.3.7" ).respond_with_data (
150
+ "" ,
161
151
status = 400 ,
162
152
content_type = self ._content_type ("country" ),
163
153
)
@@ -166,27 +156,24 @@ def test_no_body_error(self):
166
156
):
167
157
self .run_client (self .client .country ("1.2.3.7" ))
168
158
169
- @httprettified
170
159
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 ("/geoip/v2.1/country/" + "1.2.3.8" ).respond_with_json (
162
+ {"wierd" : 42 },
175
163
status = 400 ,
176
164
content_type = self ._content_type ("country" ),
177
165
)
166
+
178
167
with self .assertRaisesRegex (
179
168
HTTPError ,
180
169
"Response contains JSON but it does not " "specify code or error keys" ,
181
170
):
182
171
self .run_client (self .client .country ("1.2.3.8" ))
183
172
184
- @httprettified
185
173
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" ,
174
+
175
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + "1.2.3.9" ).respond_with_data (
176
+ "bad body" ,
190
177
status = 400 ,
191
178
content_type = self ._content_type ("country" ),
192
179
)
@@ -195,19 +182,19 @@ def test_bad_body_error(self):
195
182
):
196
183
self .run_client (self .client .country ("1.2.3.9" ))
197
184
198
- @httprettified
199
185
def test_500_error (self ):
200
- httpretty .register_uri (
201
- httpretty .GET , self .base_uri + "country/" + "1.2.3.10" , status = 500
186
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + "1.2.3.10" ).respond_with_data (
187
+ "" ,
188
+ status = 500 ,
189
+ content_type = self ._content_type ("country" ),
202
190
)
203
191
with self .assertRaisesRegex (HTTPError , r"Received a server error \(500\) for" ):
204
192
self .run_client (self .client .country ("1.2.3.10" ))
205
193
206
- @httprettified
207
194
def test_300_error (self ):
208
- httpretty . register_uri (
209
- httpretty . GET ,
210
- self . base_uri + "country/" + "1.2.3.11 " ,
195
+
196
+ self . httpserver . expect_request ( "/geoip/v2.1/country/" + "1.2.3.11" ). respond_with_data (
197
+ " " ,
211
198
status = 300 ,
212
199
content_type = self ._content_type ("country" ),
213
200
)
@@ -216,96 +203,83 @@ def test_300_error(self):
216
203
):
217
204
self .run_client (self .client .country ("1.2.3.11" ))
218
205
219
- @httprettified
220
206
def test_ip_address_required (self ):
221
207
self ._test_error (400 , "IP_ADDRESS_REQUIRED" , InvalidRequestError )
222
208
223
- @httprettified
224
209
def test_ip_address_not_found (self ):
225
210
self ._test_error (404 , "IP_ADDRESS_NOT_FOUND" , AddressNotFoundError )
226
211
227
- @httprettified
228
212
def test_ip_address_reserved (self ):
229
213
self ._test_error (400 , "IP_ADDRESS_RESERVED" , AddressNotFoundError )
230
214
231
- @httprettified
232
215
def test_permission_required (self ):
233
216
self ._test_error (403 , "PERMISSION_REQUIRED" , PermissionRequiredError )
234
217
235
- @httprettified
236
218
def test_auth_invalid (self ):
237
219
self ._test_error (400 , "AUTHORIZATION_INVALID" , AuthenticationError )
238
220
239
- @httprettified
240
221
def test_license_key_required (self ):
241
222
self ._test_error (401 , "LICENSE_KEY_REQUIRED" , AuthenticationError )
242
223
243
- @httprettified
244
224
def test_account_id_required (self ):
245
225
self ._test_error (401 , "ACCOUNT_ID_REQUIRED" , AuthenticationError )
246
226
247
- @httprettified
248
227
def test_user_id_required (self ):
249
228
self ._test_error (401 , "USER_ID_REQUIRED" , AuthenticationError )
250
229
251
- @httprettified
252
230
def test_account_id_unkown (self ):
253
231
self ._test_error (401 , "ACCOUNT_ID_UNKNOWN" , AuthenticationError )
254
232
255
- @httprettified
256
233
def test_user_id_unkown (self ):
257
234
self ._test_error (401 , "USER_ID_UNKNOWN" , AuthenticationError )
258
235
259
- @httprettified
260
236
def test_out_of_queries_error (self ):
261
237
self ._test_error (402 , "OUT_OF_QUERIES" , OutOfQueriesError )
262
238
263
239
def _test_error (self , status , error_code , error_class ):
264
240
msg = "Some error message"
265
241
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 ),
242
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + "1.2.3.18" ).respond_with_json (
243
+ body ,
270
244
status = status ,
271
245
content_type = self ._content_type ("country" ),
272
246
)
273
247
with self .assertRaisesRegex (error_class , msg ):
274
248
self .run_client (self .client .country ("1.2.3.18" ))
275
249
276
- @ httprettified
250
+
277
251
def test_unknown_error (self ):
278
252
msg = "Unknown error type"
279
253
ip = "1.2.3.19"
280
254
body = {"error" : msg , "code" : "UNKNOWN_TYPE" }
281
- httpretty .register_uri (
282
- httpretty .GET ,
283
- self .base_uri + "country/" + ip ,
284
- body = json .dumps (body ),
255
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + ip ).respond_with_json (
256
+ body ,
285
257
status = 400 ,
286
258
content_type = self ._content_type ("country" ),
287
259
)
288
260
with self .assertRaisesRegex (InvalidRequestError , msg ):
289
261
self .run_client (self .client .country (ip ))
290
262
291
- @httprettified
292
263
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
264
+
265
+ request = None
266
+ def custom_handler (r ):
267
+ nonlocal request
268
+ request = r
269
+ return ""
270
+ self .httpserver .expect_request ("/geoip/v2.1/country/" + "1.2.3.4" ).respond_with_handler (custom_handler )
271
+ try :
272
+ self .run_client (self .client .country ("1.2.3.4" ))
273
+ except Exception as e :
274
+ # just to avoid the exception
275
+ pass
276
+
277
+
302
278
303
279
self .assertEqual (
304
280
request .path , "/geoip/v2.1/country/1.2.3.4" , "correct URI is used"
305
281
)
306
282
307
- # This is to prevent breakage if header normalization in Mocket
308
- # changes again in the future.
309
283
headers = {k .lower (): v for k , v in request .headers .items ()}
310
284
self .assertEqual (headers ["accept" ], "application/json" , "correct Accept header" )
311
285
self .assertRegex (
@@ -319,12 +293,9 @@ def test_request(self):
319
293
"correct auth" ,
320
294
)
321
295
322
- @httprettified
323
296
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 ),
297
+ self .httpserver .expect_request ("/geoip/v2.1/city/1.2.3.4" ).respond_with_json (
298
+ self .country ,
328
299
status = 200 ,
329
300
content_type = self ._content_type ("city" ),
330
301
)
@@ -335,14 +306,11 @@ def test_city_ok(self):
335
306
)
336
307
self .assertTrue (city .traits .is_anycast )
337
308
338
- @httprettified
339
309
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 ),
310
+ self .httpserver .expect_request ("/geoip/v2.1/insights/" + "1.2.3.4" ).respond_with_json (
311
+ self .insights ,
344
312
status = 200 ,
345
- content_type = self ._content_type ("country " ),
313
+ content_type = self ._content_type ("insights " ),
346
314
)
347
315
insights = self .run_client (self .client .insights ("1.2.3.4" ))
348
316
self .assertEqual (
@@ -374,6 +342,7 @@ class TestClient(TestBaseClient):
374
342
def setUp (self ):
375
343
self .client_class = Client
376
344
self .client = Client (42 , "abcdef123456" )
345
+ self .client ._base_uri = self .httpserver .url_for ("/" )+ "geoip/v2.1"
377
346
378
347
def run_client (self , v ):
379
348
return v
@@ -384,6 +353,7 @@ def setUp(self):
384
353
self ._loop = asyncio .new_event_loop ()
385
354
self .client_class = AsyncClient
386
355
self .client = AsyncClient (42 , "abcdef123456" )
356
+ self .client ._base_uri = self .httpserver .url_for ("/" )+ "geoip/v2.1"
387
357
388
358
def tearDown (self ):
389
359
self ._loop .run_until_complete (self .client .close ())
0 commit comments