From 8a589361b9de4220dbb4f98f7f8b85f188626269 Mon Sep 17 00:00:00 2001 From: Shadi Romani Date: Thu, 4 Jul 2024 20:05:14 +0000 Subject: [PATCH] Remove mocket --- .github/workflows/test.yml | 3 +- pyproject.toml | 2 +- setup.cfg | 4 +- tests/webservice_test.py | 157 +++++++++++++++++-------------------- 4 files changed, 75 insertions(+), 91 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d858903..9708786 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,8 +11,7 @@ jobs: strategy: matrix: - # We don't test on Windows currently as it appears mocket may not - # work there. + # TODO: add windows-latest also platform: [ubuntu-latest, macos-latest] python-version: [3.8, 3.9, "3.10", 3.11, 3.12] diff --git a/pyproject.toml b/pyproject.toml index 1a8dffa..755e57b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ classifiers = [ [project.optional-dependencies] test = [ - "mocket>=3.12.8", + "pytest-httpserver>=1.0.10", ] [tool.setuptools.package-data] diff --git a/setup.cfg b/setup.cfg index 7156c3b..dbead82 100644 --- a/setup.cfg +++ b/setup.cfg @@ -24,7 +24,7 @@ python = [testenv:{py38,py39,py310,py311,py312}-test] deps = - mocket + pytest-httpserver pytest commands = pytest tests @@ -43,6 +43,8 @@ commands = flake8 geoip2 [testenv:py312-mypy] deps = mypy + pytest_httpserver + pytest types-requests voluptuous-stubs commands = mypy geoip2 tests diff --git a/tests/webservice_test.py b/tests/webservice_test.py index 4e8a7a7..ef5656b 100644 --- a/tests/webservice_test.py +++ b/tests/webservice_test.py @@ -8,13 +8,10 @@ import sys from typing import cast, Dict import unittest +import pytest_httpserver +import pytest sys.path.append("..") - -# httpretty currently doesn't work, but mocket with the compat interface -# does. -from mocket import Mocket # type: ignore -from mocket.plugins.httpretty import httpretty, httprettified # type: ignore import geoip2 from geoip2.errors import ( AddressNotFoundError, @@ -29,7 +26,6 @@ class TestBaseClient(unittest.TestCase): - base_uri = "https://geoip.maxmind.com/geoip/v2.1/" country = { "continent": {"code": "NA", "geoname_id": 42, "names": {"en": "North America"}}, "country": { @@ -64,12 +60,13 @@ def _content_type(self, endpoint): + "+json; charset=UTF-8; version=1.0" ) - @httprettified + @pytest.fixture(autouse=True) + def setup_httpserver(self, httpserver: pytest_httpserver.HTTPServer): + self.httpserver = httpserver + def test_country_ok(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/1.2.3.4", - body=json.dumps(self.country), + self.httpserver.expect_request("/geoip/v2.1/country/1.2.3.4").respond_with_json( + self.country, status=200, content_type=self._content_type("country"), ) @@ -111,12 +108,9 @@ def test_country_ok(self): self.assertTrue(country.traits.is_anycast) self.assertEqual(country.raw, self.country, "raw response is correct") - @httprettified def test_me(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/me", - body=json.dumps(self.country), + self.httpserver.expect_request("/geoip/v2.1/country/me").respond_with_json( + self.country, status=200, content_type=self._content_type("country"), ) @@ -131,33 +125,29 @@ def test_me(self): "country('me') returns Country object", ) - @httprettified def test_200_error(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/1.1.1.1", - body="", + self.httpserver.expect_request("/geoip/v2.1/country/1.1.1.1").respond_with_data( + "", status=200, content_type=self._content_type("country"), ) + with self.assertRaisesRegex( GeoIP2Error, "could not decode the response as JSON" ): self.run_client(self.client.country("1.1.1.1")) - @httprettified def test_bad_ip_address(self): with self.assertRaisesRegex( ValueError, "'1.2.3' does not appear to be an IPv4 " "or IPv6 address" ): self.run_client(self.client.country("1.2.3")) - @httprettified def test_no_body_error(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + "1.2.3.7", - body="", + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.7" + ).respond_with_data( + "", status=400, content_type=self._content_type("country"), ) @@ -166,27 +156,28 @@ def test_no_body_error(self): ): self.run_client(self.client.country("1.2.3.7")) - @httprettified def test_weird_body_error(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + "1.2.3.8", - body='{"wierd": 42}', + + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.8" + ).respond_with_json( + {"wierd": 42}, status=400, content_type=self._content_type("country"), ) + with self.assertRaisesRegex( HTTPError, "Response contains JSON but it does not " "specify code or error keys", ): self.run_client(self.client.country("1.2.3.8")) - @httprettified def test_bad_body_error(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + "1.2.3.9", - body="bad body", + + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.9" + ).respond_with_data( + "bad body", status=400, content_type=self._content_type("country"), ) @@ -195,19 +186,23 @@ def test_bad_body_error(self): ): self.run_client(self.client.country("1.2.3.9")) - @httprettified def test_500_error(self): - httpretty.register_uri( - httpretty.GET, self.base_uri + "country/" + "1.2.3.10", status=500 + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.10" + ).respond_with_data( + "", + status=500, + content_type=self._content_type("country"), ) with self.assertRaisesRegex(HTTPError, r"Received a server error \(500\) for"): self.run_client(self.client.country("1.2.3.10")) - @httprettified def test_300_error(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + "1.2.3.11", + + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.11" + ).respond_with_data( + "", status=300, content_type=self._content_type("country"), ) @@ -216,96 +211,86 @@ def test_300_error(self): ): self.run_client(self.client.country("1.2.3.11")) - @httprettified def test_ip_address_required(self): self._test_error(400, "IP_ADDRESS_REQUIRED", InvalidRequestError) - @httprettified def test_ip_address_not_found(self): self._test_error(404, "IP_ADDRESS_NOT_FOUND", AddressNotFoundError) - @httprettified def test_ip_address_reserved(self): self._test_error(400, "IP_ADDRESS_RESERVED", AddressNotFoundError) - @httprettified def test_permission_required(self): self._test_error(403, "PERMISSION_REQUIRED", PermissionRequiredError) - @httprettified def test_auth_invalid(self): self._test_error(400, "AUTHORIZATION_INVALID", AuthenticationError) - @httprettified def test_license_key_required(self): self._test_error(401, "LICENSE_KEY_REQUIRED", AuthenticationError) - @httprettified def test_account_id_required(self): self._test_error(401, "ACCOUNT_ID_REQUIRED", AuthenticationError) - @httprettified def test_user_id_required(self): self._test_error(401, "USER_ID_REQUIRED", AuthenticationError) - @httprettified def test_account_id_unkown(self): self._test_error(401, "ACCOUNT_ID_UNKNOWN", AuthenticationError) - @httprettified def test_user_id_unkown(self): self._test_error(401, "USER_ID_UNKNOWN", AuthenticationError) - @httprettified def test_out_of_queries_error(self): self._test_error(402, "OUT_OF_QUERIES", OutOfQueriesError) def _test_error(self, status, error_code, error_class): msg = "Some error message" body = {"error": msg, "code": error_code} - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/1.2.3.18", - body=json.dumps(body), + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.18" + ).respond_with_json( + body, status=status, content_type=self._content_type("country"), ) with self.assertRaisesRegex(error_class, msg): self.run_client(self.client.country("1.2.3.18")) - @httprettified def test_unknown_error(self): msg = "Unknown error type" ip = "1.2.3.19" body = {"error": msg, "code": "UNKNOWN_TYPE"} - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + ip, - body=json.dumps(body), + self.httpserver.expect_request("/geoip/v2.1/country/" + ip).respond_with_json( + body, status=400, content_type=self._content_type("country"), ) with self.assertRaisesRegex(InvalidRequestError, msg): self.run_client(self.client.country(ip)) - @httprettified def test_request(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "country/" + "1.2.3.4", - body=json.dumps(self.country), - status=200, - content_type=self._content_type("country"), - ) - self.run_client(self.client.country("1.2.3.4")) - request = httpretty.last_request + + request = None + + def custom_handler(r): + nonlocal request + request = r + return "" + + self.httpserver.expect_request( + "/geoip/v2.1/country/" + "1.2.3.4" + ).respond_with_handler(custom_handler) + try: + self.run_client(self.client.country("1.2.3.4")) + except Exception as e: + # just to avoid the exception + pass self.assertEqual( request.path, "/geoip/v2.1/country/1.2.3.4", "correct URI is used" ) - # This is to prevent breakage if header normalization in Mocket - # changes again in the future. headers = {k.lower(): v for k, v in request.headers.items()} self.assertEqual(headers["accept"], "application/json", "correct Accept header") self.assertRegex( @@ -319,12 +304,9 @@ def test_request(self): "correct auth", ) - @httprettified def test_city_ok(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "city/" + "1.2.3.4", - body=json.dumps(self.country), + self.httpserver.expect_request("/geoip/v2.1/city/1.2.3.4").respond_with_json( + self.country, status=200, content_type=self._content_type("city"), ) @@ -335,14 +317,13 @@ def test_city_ok(self): ) self.assertTrue(city.traits.is_anycast) - @httprettified def test_insights_ok(self): - httpretty.register_uri( - httpretty.GET, - self.base_uri + "insights/1.2.3.4", - body=json.dumps(self.insights), + self.httpserver.expect_request( + "/geoip/v2.1/insights/" + "1.2.3.4" + ).respond_with_json( + self.insights, status=200, - content_type=self._content_type("country"), + content_type=self._content_type("insights"), ) insights = self.run_client(self.client.insights("1.2.3.4")) self.assertEqual( @@ -374,6 +355,7 @@ class TestClient(TestBaseClient): def setUp(self): self.client_class = Client self.client = Client(42, "abcdef123456") + self.client._base_uri = self.httpserver.url_for("/") + "geoip/v2.1" def run_client(self, v): return v @@ -384,6 +366,7 @@ def setUp(self): self._loop = asyncio.new_event_loop() self.client_class = AsyncClient self.client = AsyncClient(42, "abcdef123456") + self.client._base_uri = self.httpserver.url_for("/") + "geoip/v2.1" def tearDown(self): self._loop.run_until_complete(self.client.close())