Package: mocket
A socket mock frameworkfor all kinds of socketanimals, web-clients included - with gevent/asyncio/SSL support…and then MicroPython’surequests(mocket >= 3.9.1)Outside GitHubMocket packages are available forArch Linux,openSUSE,NixOS,ALT LinuxandNetBSD.VersioningStarting from3.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.FYI: the last version compatible with Python 2.7 is3.9.4, bugfixing or backporting of features introduced after that release will only be available as commercial support.Support itStarthe project on GitHub,Buy Me a Coffeeclicking the button below or, even better, contribute with patches or documentation.How to use itRead the following blog posts if you want to have a big picture of whatMocketis capable of:https://medium.com/p/mocket-is-alive-and-is-fighting-with-us-b2810d52597ahttps://hackernoon.com/make-development-great-again-faab769d264ehttps://hackernoon.com/httpretty-now-supports-asyncio-e310814704c6https://medium.com/@mindflayer/how-to-make-your-tests-fail-when-they-try-to-access-the-network-python-eb80090a6d24https://medium.com/@mindflayer/testing-in-an-asyncio-world-a9a0ad41b0c5The starting point to understand how to useMocketto write a custom mock is the following example:https://github.com/mindflayer/mocketoyAs next step, you are invited to have a look at the implementation of both the mocks it provides:HTTP mock (similar to HTTPretty) -https://github.com/mindflayer/python-mocket/blob/master/mocket/mockhttp.pyRedis mock (basic implementation) -https://github.com/mindflayer/python-mocket/blob/master/mocket/mockredis.pyPlease also have a look at the huge test suite:Tests module athttps://github.com/mindflayer/python-mocket/tree/master/testsInstallationUsing pip:$ pip install mocketSpeedupsMocket usesxxhashwhen available instead ofhashlib.md5for creating hashes, you can install it as follows:$ pip install mocket[speedups]IssuesWhen opening anIssue, please add few lines of code as failing test, or -better- open its relativePull requestadding this test to our test suite.Example of how to mock an HTTP[S] callLet’s create a new virtualenv with all we need:$ python3 -m venv example
$ source example/bin/activate
$ pip install pytest requests mocketAs second step, we create anexample.pyfile as the following one:importjsonfrommocketimportmocketizefrommocket.mockhttpimportEntryimportrequestsimportpytest@pytest.fixturedefresponse():return{"integer":1,"string":"asd","boolean":False,}@mocketize# use its decoratordeftest_json(response):url_to_mock='https://testme.org/json'Entry.single_register(Entry.GET,url_to_mock,body=json.dumps(response),headers={'content-type':'application/json'})mocked_response=requests.get(url_to_mock).json()assertresponse==mocked_response# OR use its context managerfrommocketimportMocketizerdeftest_json_with_context_manager(response):url_to_mock='https://testme.org/json'Entry.single_register(Entry.GET,url_to_mock,body=json.dumps(response),headers={'content-type':'application/json'})withMocketizer():mocked_response=requests.get(url_to_mock).json()assertresponse==mocked_responseLet’s fire our example test:$ py.test example.pyHow to make Mocket fail when it tries to write to a realsocket?NEW!!! Sometimes you just want your tests to fail when they attempt to use the network.withMocketizer(strict_mode=True):withpytest.raises(StrictMocketException):requests.get("https://duckduckgo.com/")# OR@mocketize(strict_mode=True)deftest_get():withpytest.raises(StrictMocketException):requests.get("https://duckduckgo.com/")You can specify exceptions as a list of hosts or host-port pairs.withMocketizer(strict_mode=True,strict_mode_allowed=["localhost",("intake.ourmetrics.net",443)]):...# OR@mocketize(strict_mode=True,strict_mode_allowed=["localhost",("intake.ourmetrics.net",443)])deftest_get():...How to be sure that all the Entry instances have been served?Add this instruction at the end of the test execution:Mocket.assert_fail_if_entries_not_served()Example of how to fake socket errorsIt’s very important that we test non-happy paths.@mocketizedeftest_raise_exception(self):url="http://github.com/fluidicon.png"Entry.single_register(Entry.GET,url,exception=socket.error())withself.assertRaises(requests.exceptions.ConnectionError):requests.get(url)Example of how to record real socket trafficYou probably know whatVCRpyis capable of, that’s themocket’s way of achieving it:@mocketize(truesocket_recording_dir=tempfile.mkdtemp())deftest_truesendall_with_recording_https():url='https://httpbin.org/ip'requests.get(url,headers={"Accept":"application/json"})resp=requests.get(url,headers={"Accept":"application/json"})assertresp.status_code==200dump_filename=os.path.join(Mocket.get_truesocket_recording_dir(),Mocket.get_namespace()+'.json',)withio.open(dump_filename)asf:response=json.load(f)assertlen(response['httpbin.org']['443'].keys())==1HTTPretty compatibility layerMocket HTTP mock can work asHTTPrettyreplacement for many different use cases. Two main features are missing:URL entries containing regular expressions;response body from functions (used mostly to fake errors,mocketdoesn’t need to do it this way).Two features which are against the Zen of Python, at least imho (mindflayer), but of course I am open to call it into question.Example:importjsonimportaiohttpimportasynciofromunittestimportTestCasefrommocket.plugins.httprettyimporthttpretty,httprettifiedclassAioHttpEntryTestCase(TestCase):@httprettifieddeftest_https_session(self):url='https://httpbin.org/ip'httpretty.register_uri(httpretty.GET,url,body=json.dumps(dict(origin='127.0.0.1')),)asyncdefmain(l):asyncwithaiohttp.ClientSession(loop=l,timeout=aiohttp.ClientTimeout(total=3))assession:asyncwithsession.get(url)asget_response:assertget_response.status==200assertawaitget_response.text()=='{"origin": "127.0.0.1"}'loop=asyncio.new_event_loop()loop.set_debug(True)loop.run_until_complete(main(loop))What about the other socket animals?UsingMocketwith asyncio based clients:$ pip install aiohttpExample:classAioHttpEntryTestCase(TestCase):@mocketizedeftest_http_session(self):url='http://httpbin.org/ip'body="asd"*100Entry.single_register(Entry.GET,url,body=body,status=404)Entry.single_register(Entry.POST,url,body=body*2,status=201)asyncdefmain(l):asyncwithaiohttp.ClientSession(loop=l,timeout=aiohttp.ClientTimeout(total=3))assession:asyncwithsession.get(url)asget_response:assertget_response.status==404assertawaitget_response.text()==bodyasyncwithsession.post(url,data=body*6)aspost_response:assertpost_response.status==201assertawaitpost_response.text()==body*2loop=asyncio.new_event_loop()loop.run_until_complete(main(loop))# or again with a unittest.IsolatedAsyncioTestCasefrommocket.async_mocketimportasync_mocketizeclassAioHttpEntryTestCase(IsolatedAsyncioTestCase):@async_mocketizeasyncdeftest_http_session(self):url='http://httpbin.org/ip'body="asd"*100Entry.single_register(Entry.GET,url,body=body,status=404)Entry.single_register(Entry.POST,url,body=body*2,status=201)asyncwithaiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=3))assession:asyncwithsession.get(url)asget_response:assertget_response.status==404assertawaitget_response.text()==bodyasyncwithsession.post(url,data=body*6)aspost_response:assertpost_response.status==201assertawaitpost_response.text()==body*2assertMocket.last_request().method=='POST'assertMocket.last_request().body==body*6Works well with othersUsingMocketaspookengine:$ pip install mocket[pook]Example:importpookfrommocket.plugins.pook_mock_engineimportMocketEnginepook.set_mock_engine(MocketEngine)pook.on()url='http://twitter.com/api/1/foobar'status=404response_json={'error':'foo'}mock=pook.get(url,headers={'content-type':'application/json'},reply=status,response_json=response_json,)mock.persist()requests.get(url)assertmock.calls==1resp=requests.get(url)assertresp.status_code==statusassertresp.json()==response_jsonassertmock.calls==2First appearanceEuroPython 2013, FlorenceVideo:https://www.youtube.com/watch?v=-LvXbl5d02USlides:https://prezi.com/tmuiaugamsti/mocket/Slides as PDF:https://ep2013.europython.eu/media/conference/slides/mocket-a-socket-mock-framework.pdf