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