{"id":13501835,"url":"https://github.com/mindflayer/python-mocket","last_synced_at":"2025-05-15T01:04:44.484Z","repository":{"id":8276549,"uuid":"9766348","full_name":"mindflayer/python-mocket","owner":"mindflayer","description":"a socket mock framework - for all kinds of socket animals, web-clients included","archived":false,"fork":false,"pushed_at":"2025-03-26T12:17:12.000Z","size":621,"stargazers_count":293,"open_issues_count":4,"forks_count":42,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-04-06T19:05:55.723Z","etag":null,"topics":["aiohttp","asyncio","coverage","framework","http","httpretty","https","micropython","mock","mocket","mocking","python","socket","socket-communication","socket-programming","ssl","tdd","tdd-utilities","testing","urequests"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mindflayer.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-04-30T07:44:28.000Z","updated_at":"2025-03-27T13:56:16.000Z","dependencies_parsed_at":"2023-10-16T11:29:50.997Z","dependency_job_id":"0db03d5c-9e49-435f-ad7b-cc385a5442bb","html_url":"https://github.com/mindflayer/python-mocket","commit_stats":{"total_commits":546,"total_committers":28,"mean_commits":19.5,"dds":0.3589743589743589,"last_synced_commit":"87f1dec8d513e6c47f842e3efd4802cfb2f6e4e2"},"previous_names":[],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindflayer%2Fpython-mocket","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindflayer%2Fpython-mocket/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindflayer%2Fpython-mocket/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindflayer%2Fpython-mocket/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mindflayer","download_url":"https://codeload.github.com/mindflayer/python-mocket/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248786052,"owners_count":21161390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aiohttp","asyncio","coverage","framework","http","httpretty","https","micropython","mock","mocket","mocking","python","socket","socket-communication","socket-programming","ssl","tdd","tdd-utilities","testing","urequests"],"created_at":"2024-07-31T22:01:52.554Z","updated_at":"2025-04-13T21:32:39.454Z","avatar_url":"https://github.com/mindflayer.png","language":"Python","readme":"===============\nmocket /mɔˈkɛt/\n===============\n\n.. image:: https://github.com/mindflayer/python-mocket/actions/workflows/main.yml/badge.svg?branch=main\n    :target: https://github.com/mindflayer/python-mocket/actions?query=workflow%3A%22Mocket%27s+CI%22\n\n.. image:: https://codecov.io/github/mindflayer/python-mocket/graph/badge.svg?token=htRySebRBt\n    :target: https://codecov.io/github/mindflayer/python-mocket\n\n.. image:: https://app.codacy.com/project/badge/Grade/6327640518ce42adaf59368217028f14\n    :target: https://www.codacy.com/gh/mindflayer/python-mocket/dashboard\n\n.. image:: https://img.shields.io/pypi/dm/mocket\n    :target: https://pypistats.org/packages/mocket\n\n\nA socket mock framework\n-------------------------\n    for all kinds of socket *animals*, web-clients included - with gevent/asyncio/SSL support\n\n...and then MicroPython's *urequests* (*mocket \u003e= 3.9.1*)\n\nOutside GitHub\n==============\n\nMocket packages are available for `openSUSE`_, `NixOS`_, `ALT Linux`_, `NetBSD`_, and of course from `PyPI`_.\n\n.. _`openSUSE`: https://software.opensuse.org/search?baseproject=ALL\u0026q=mocket\n.. _`NixOS`: https://search.nixos.org/packages?query=mocket\n.. _`ALT Linux`: https://packages.altlinux.org/en/sisyphus/srpms/python3-module-mocket/\n.. _`NetBSD`: https://cdn.netbsd.org/pub/pkgsrc/current/pkgsrc/devel/py-mocket/index.html\n.. _`PyPI`: https://pypi.org/project/mocket/\n\n\nVersioning\n==========\nStarting from *3.7.0*, Mocket major version will follow the same numbering pattern as Python's and therefore indicate the most recent Python version that is supported.\n\nFYI: the last version compatible with Python 2.7 is *3.9.4*, bugfixing or backporting of features introduced after that release will only be available as commercial support.\n\nSupport it\n==========\n*Star* the project on GitHub, *Buy Me a Coffee* clicking the button below or, even better, contribute with patches or documentation.\n\n.. image:: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png\n     :target: https://www.buymeacoffee.com/mocket\n     :alt: Buy Me A Coffee\n\nHow to use it\n=============\nRead the following blog posts if you want to have a big picture of what *Mocket* is capable of:\n\n- https://medium.com/p/mocket-is-alive-and-is-fighting-with-us-b2810d52597a\n- https://hackernoon.com/make-development-great-again-faab769d264e\n- https://hackernoon.com/httpretty-now-supports-asyncio-e310814704c6\n- https://medium.com/@mindflayer/how-to-make-your-tests-fail-when-they-try-to-access-the-network-python-eb80090a6d24\n- https://medium.com/@mindflayer/testing-in-an-asyncio-world-a9a0ad41b0c5\n\nThe starting point to understand how to use *Mocket* to write a custom mock is the following example:\n\n- https://github.com/mindflayer/mocketoy\n\nAs next step, you are invited to have a look at the implementation of both the mocks it provides:\n\n- HTTP mock (similar to HTTPretty) - https://github.com/mindflayer/python-mocket/blob/master/mocket/mocks/mockhttp.py\n- Redis mock (basic implementation) - https://github.com/mindflayer/python-mocket/blob/master/mocket/mocks/mockredis.py\n\nPlease also have a look at the huge test suite:\n\n- Tests module at https://github.com/mindflayer/python-mocket/tree/master/tests\n\nInstallation\n============\nUsing pip::\n\n    $ pip install mocket\n\nSpeedups\n========\nMocket uses **xxhash** when available instead of *hashlib.md5* for creating hashes, you can install it as follows::\n\n    $ pip install mocket[speedups]\n\nIssues\n============\nWhen opening an **Issue**, please add few lines of code as failing test, or -better- open its relative **Pull request** adding this test to our test suite.\n\nExample of how to mock an HTTP[S] call\n======================================\nLet's create a new virtualenv with all we need::\n\n    $ python3 -m venv example\n    $ source example/bin/activate\n    $ pip install pytest requests mocket\n\nAs second step, we create an `example.py` file as the following one:\n\n.. code-block:: python\n\n    import json\n\n    from mocket import mocketize\n    from mocket.mockhttp import Entry\n    import requests\n    import pytest\n\n\n    @pytest.fixture\n    def response():\n        return {\n            \"integer\": 1,\n            \"string\": \"asd\",\n            \"boolean\": False,\n        }\n\n\n    @mocketize  # use its decorator\n    def test_json(response):\n        url_to_mock = 'https://testme.org/json'\n\n        Entry.single_register(\n            Entry.GET,\n            url_to_mock,\n            body=json.dumps(response),\n            headers={'content-type': 'application/json'}\n        )\n\n        mocked_response = requests.get(url_to_mock).json()\n\n        assert response == mocked_response\n\n    # OR use its context manager\n    from mocket import Mocketizer\n\n    def test_json_with_context_manager(response):\n        url_to_mock = 'https://testme.org/json'\n\n        Entry.single_register(\n            Entry.GET,\n            url_to_mock,\n            body=json.dumps(response),\n            headers={'content-type': 'application/json'}\n        )\n\n        with Mocketizer():\n            mocked_response = requests.get(url_to_mock).json()\n\n        assert response == mocked_response\n\nLet's fire our example test::\n\n    $ py.test example.py\n\nHow to make Mocket fail when it tries to write to a real `socket`?\n==================================================================\nNEW!!! Sometimes you just want your tests to fail when they attempt to use the network.\n\n.. code-block:: python\n\n    with Mocketizer(strict_mode=True):\n        with pytest.raises(StrictMocketException):\n            requests.get(\"https://duckduckgo.com/\")\n\n    # OR\n\n    @mocketize(strict_mode=True)\n    def test_get():\n        with pytest.raises(StrictMocketException):\n            requests.get(\"https://duckduckgo.com/\")\n\nYou can specify exceptions as a list of hosts or host-port pairs.\n\n.. code-block:: python\n\n    with Mocketizer(strict_mode=True, strict_mode_allowed=[\"localhost\", (\"intake.ourmetrics.net\", 443)]):\n        ...\n\n    # OR\n\n    @mocketize(strict_mode=True, strict_mode_allowed=[\"localhost\", (\"intake.ourmetrics.net\", 443)])\n    def test_get():\n        ...\n\n\nHow to be sure that all the Entry instances have been served?\n=============================================================\nAdd this instruction at the end of the test execution:\n\n.. code-block:: python\n\n    Mocket.assert_fail_if_entries_not_served()\n\nExample of how to fake socket errors\n====================================\n\nIt's very important that we test non-happy paths.\n\n.. code-block:: python\n\n    @mocketize\n    def test_raise_exception(self):\n        url = \"http://github.com/fluidicon.png\"\n        Entry.single_register(Entry.GET, url, exception=socket.error())\n        with self.assertRaises(requests.exceptions.ConnectionError):\n            requests.get(url)\n\nExample of how to record real socket traffic\n============================================\n\nYou probably know what *VCRpy* is capable of, that's the *mocket*'s way of achieving it:\n\n.. code-block:: python\n\n    @mocketize(truesocket_recording_dir=tempfile.mkdtemp())\n    def test_truesendall_with_recording_https():\n        url = 'https://httpbin.org/ip'\n\n        requests.get(url, headers={\"Accept\": \"application/json\"})\n        resp = requests.get(url, headers={\"Accept\": \"application/json\"})\n        assert resp.status_code == 200\n\n        dump_filename = os.path.join(\n            Mocket.get_truesocket_recording_dir(),\n            Mocket.get_namespace() + '.json',\n        )\n        with io.open(dump_filename) as f:\n            response = json.load(f)\n\n        assert len(response['httpbin.org']['443'].keys()) == 1\n\nHTTPretty compatibility layer\n=============================\nMocket HTTP mock can work as *HTTPretty* replacement for many different use cases. Two main features are missing:\n\n- URL entries containing regular expressions;\n- response body from functions (used mostly to fake errors, *mocket* doesn't need to do it this way).\n\nTwo features which are against the Zen of Python, at least imho (*mindflayer*), but of course I am open to call it into question.\n\nExample:\n\n.. code-block:: python\n\n    import json\n\n    import aiohttp\n    import asyncio\n    from unittest import TestCase\n\n    from mocket.plugins.httpretty import httpretty, httprettified\n\n\n    class AioHttpEntryTestCase(TestCase):\n        @httprettified\n        def test_https_session(self):\n            url = 'https://httpbin.org/ip'\n            httpretty.register_uri(\n                httpretty.GET,\n                url,\n                body=json.dumps(dict(origin='127.0.0.1')),\n            )\n\n            async def main(l):\n                async with aiohttp.ClientSession(\n                    loop=l, timeout=aiohttp.ClientTimeout(total=3)\n                ) as session:\n                    async with session.get(url) as get_response:\n                        assert get_response.status == 200\n                        assert await get_response.text() == '{\"origin\": \"127.0.0.1\"}'\n\n            loop = asyncio.new_event_loop()\n            loop.set_debug(True)\n            loop.run_until_complete(main(loop))\n\nWhat about the other socket animals?\n====================================\nUsing *Mocket* with asyncio based clients::\n\n    $ pip install aiohttp\n\nExample:\n\n.. code-block:: python\n\n    # `aiohttp` creates SSLContext instances at import-time\n    # that's why Mocket would get stuck when dealing with HTTP\n    # Importing the module while Mocket is in control (inside a\n    # decorated test function or using its context manager would\n    # be enough for making it work), the alternative is using a\n    # custom TCPConnector which always return a FakeSSLContext\n    # from Mocket like this example is showing.\n    import aiohttp\n    import pytest\n\n    from mocket import async_mocketize\n    from mocket.mockhttp import Entry\n    from mocket.plugins.aiohttp_connector import MocketTCPConnector\n\n\n    @pytest.mark.asyncio\n    @async_mocketize\n    async def test_aiohttp():\n        \"\"\"\n        The alternative to using the custom `connector` would be importing\n        `aiohttp` when Mocket is already in control (inside the decorated test).\n        \"\"\"\n\n        url = \"https://bar.foo/\"\n        data = {\"message\": \"Hello\"}\n\n        Entry.single_register(\n\t    Entry.GET,\n\t    url,\n\t    body=json.dumps(data),\n\t    headers={\"content-type\": \"application/json\"},\n        )\n\n        async with aiohttp.ClientSession(\n\t    timeout=aiohttp.ClientTimeout(total=3), connector=MocketTCPConnector()\n        ) as session, session.get(url) as response:\n\t    response = await response.json()\n\t    assert response == data\n\n\nWorks well with others\n=======================\nUsing *Mocket* as pook_ engine::\n\n    $ pip install mocket[pook]\n\n.. _pook: https://pypi.python.org/pypi/pook\n\nExample:\n\n.. code-block:: python\n\n    import pook\n    from mocket.plugins.pook_mock_engine import MocketEngine\n\n    pook.set_mock_engine(MocketEngine)\n\n    pook.on()\n\n    url = 'http://twitter.com/api/1/foobar'\n    status = 404\n    response_json = {'error': 'foo'}\n\n    mock = pook.get(\n        url,\n        headers={'content-type': 'application/json'},\n        reply=status,\n        response_json=response_json,\n    )\n    mock.persist()\n\n    requests.get(url)\n    assert mock.calls == 1\n\n    resp = requests.get(url)\n    assert resp.status_code == status\n    assert resp.json() == response_json\n    assert mock.calls == 2\n\nFirst appearance\n================\nEuroPython 2013, Florence\n\n- Video: https://www.youtube.com/watch?v=-LvXbl5d02U\n- Slides: https://prezi.com/tmuiaugamsti/mocket/\n- Slides as PDF: https://ep2013.europython.eu/media/conference/slides/mocket-a-socket-mock-framework.pdf\n","funding_links":["https://www.buymeacoffee.com/mocket"],"categories":["Testing","资源列表","Python","测试","File Manipulation","Mock and Stub","Web Testing","Testing [🔝](#readme)","Awesome Python"],"sub_categories":["测试","HTTP Clients","Testing"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindflayer%2Fpython-mocket","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmindflayer%2Fpython-mocket","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindflayer%2Fpython-mocket/lists"}