for all kinds of socket animals, web-clients included - with gevent/asyncio/SSL support
Star the project on GitHub, Buy Me a Coffee or, even better, contribute with patches or documentation.
Read these three blog posts if you want to have a big picture of what Mocket is capable of:
- https://medium.com/p/mocket-is-alive-and-is-fighting-with-us-b2810d52597a
- https://hackernoon.com/make-development-great-again-faab769d264e
- https://hackernoon.com/httpretty-now-supports-asyncio-e310814704c6
The starting point to understand how to use Mocket to write a custom mock is the following example:
As next step, you are invited to have a look at both the implementation of the two mocks it provides:
- HTTP mock (similar to HTTPretty) - https://github.com/mindflayer/python-mocket/blob/master/mocket/mockhttp.py
- Redis mock (basic implementation) - https://github.com/mindflayer/python-mocket/blob/master/mocket/mockredis.py
Please also have a look at the huge test suite:
- Tests module at https://github.com/mindflayer/python-mocket/tree/master/tests
Using pip:
$ pip install mocket
When 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.
Let's create a new virtualenv with all we need:
$ virtualenv example $ source example/bin/activate $ pip install pytest requests mocket
As second step, we create an example.py file as the following one:
import json
from mocket import mocketize
from mocket.mockhttp import Entry
import requests
import pytest
@pytest.fixture
def response():
return {
"integer": 1,
"string": "asd",
"boolean": False,
}
@mocketize # use its decorator
def test_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()
assert response == mocked_response
# OR use its context manager
from mocket import Mocketizer
def test_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'}
)
with Mocketizer():
mocked_response = requests.get(url_to_mock).json()
assert response == mocked_response
Let's fire our example test:
$ py.test example.py
Mocket HTTP mock can work as HTTPretty replacement for many different use cases. Two main features are missing:
- URL entries containing regular expressions;
- response body from functions.
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:
import json
import aiohttp
import asyncio
import async_timeout
from unittest import TestCase
from mocket.plugins.httpretty import HTTPretty, httprettified
class AioHttpEntryTestCase(TestCase):
@httprettified
def test_https_session(self):
url = 'https://httpbin.org/ip'
HTTPretty.register_uri(
HTTPretty.GET,
url,
body=json.dumps(dict(origin='127.0.0.1')),
)
async def main(l):
async with aiohttp.ClientSession(loop=l) as session:
with async_timeout.timeout(3):
async with session.get(url) as get_response:
assert get_response.status == 200
assert await get_response.text() == '{"origin": "127.0.0.1"}'
loop = asyncio.get_event_loop()
loop.set_debug(True)
loop.run_until_complete(main(loop))
Using Mocket with asyncio based clients:
$ pip install aiohttp
Example:
class AioHttpEntryTestCase(TestCase):
@mocketize
def test_http_session(self):
url = 'http://httpbin.org/ip'
body = "asd" * 100
Entry.single_register(Entry.GET, url, body=body, status=404)
Entry.single_register(Entry.POST, url, body=body*2, status=201)
async def main(l):
async with aiohttp.ClientSession(loop=l) as session:
with async_timeout.timeout(3):
async with session.get(url) as get_response:
assert get_response.status == 404
assert await get_response.text() == body
with async_timeout.timeout(3):
async with session.post(url, data=body * 6) as post_response:
assert post_response.status == 201
assert await post_response.text() == body * 2
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
Using Mocket as pook engine:
$ pip install mocket[pook]
Example:
import pook
from mocket.plugins.pook_mock_engine import MocketEngine
pook.set_mock_engine(MocketEngine)
pook.on()
url = 'http://twitter.com/api/1/foobar'
status = 404
response_json = {'error': 'foo'}
mock = pook.get(
url,
headers={'content-type': 'application/json'},
reply=status,
response_json=response_json,
)
mock.persist()
requests.get(url)
assert mock.calls == 1
resp = requests.get(url)
assert resp.status_code == status
assert resp.json() == response_json
assert mock.calls == 2
EuroPython 2013, Florence