Examples¶
Basic mocking example using requests¶
import pook
import requests
# Enable mock engine
pook.on()
pook.get('httpbin.org/ip',
reply=403, response_type='json',
response_headers={'server': 'pook'},
response_json={'error': 'not found'})
pook.get('httpbin.org/headers',
reply=404, response_type='json',
response_headers={'server': 'pook'},
response_json={'error': 'not found'})
res = requests.get('http://httpbin.org/ip')
print('Status:', res.status_code)
print('Headers:', res.headers)
print('Body:', res.json())
res = requests.get('http://httpbin.org/headers')
print('Status:', res.status_code)
print('Headers:', res.headers)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
Chainable API DSL¶
import json
import pook
import requests
# Enable mock engine
pook.on()
(pook.post('httpbin.org/post')
.json({'foo': 'bar'})
.type('json')
.header('Client', 'requests')
.reply(204)
.headers({'server': 'pook'})
.json({'error': 'simulated'}))
res = requests.post('http://httpbin.org/post',
data=json.dumps({'foo': 'bar'}),
headers={'Client': 'requests',
'Content-Type': 'application/json'})
print('Status:', res.status_code)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
Context manager for isolated mocking¶
import pook
import requests
with pook.use():
pook.get('httpbin.org/ip', reply=403,
response_headers={'pepe': 'lopez'},
response_json={'error': 'not found'})
res = requests.get('http://httpbin.org/ip')
print('Status:', res.status_code)
print('Headers:', res.headers)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
Single mock context manager definition for isolated mocking¶
import pook
import requests
# Define a new mock that will be only active within the context manager
with pook.get('httpbin.org/ip', reply=403,
response_headers={'pepe': 'lopez'},
response_json={'error': 'not found'}) as mock:
res = requests.get('http://httpbin.org/ip')
print('#1 Status:', res.status_code)
print('#1 Headers:', res.headers)
print('#1 Body:', res.json())
print('----------------')
res = requests.get('http://httpbin.org/ip')
print('#2 Status:', res.status_code)
print('#2 Headers:', res.headers)
print('#2 Body:', res.json())
print('----------------')
print('Mock is done:', mock.isdone())
print('Mock matches:', mock.total_matches)
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
# Explicitly disable mock engine
pook.off()
# Perform a real HTTP request since we are running the
# request outside of the context manager
res = requests.get('http://httpbin.org/ip')
print('#3 Status:', res.status_code)
print('#3 Headers:', res.headers)
print('#3 Body:', res.json())
Declaring mocks as decorators¶
import pook
import requests
@pook.get('http://httpbin.org/status/500', reply=204)
@pook.get('http://httpbin.org/status/400', reply=200, persist=True)
def fetch(url):
return requests.get(url)
# Test function
res = fetch('http://httpbin.org/status/400')
print('#1 status:', res.status_code)
res = fetch('http://httpbin.org/status/500')
print('#2 status:', res.status_code)
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
# Disable mock engine
pook.off()
# Test real request
res = requests.get('http://httpbin.org/status/400')
print('Test status:', res.status_code)
Activating the mock engine via decorator within the function context¶
import pook
import requests
@pook.on
def run():
pook.get('httpbin.org/ip', reply=403,
response_headers={'pepe': 'lopez'},
response_json={'error': 'not found'})
res = requests.get('http://httpbin.org/ip')
print('Status:', res.status_code)
print('Headers:', res.headers)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
run()
Activating the mock engine via decorator within an async coroutine function context¶
# flake8: noqa
import pook
import asyncio
import aiohttp
#
# NOTE: requires Python 3.5+
#
@pook.on
async def run():
pook.get('httpbin.org/ip', reply=403,
response_headers={'pepe': 'lopez'},
response_json={'error': 'not found'})
async with aiohttp.ClientSession(loop=loop) as session:
async with session.get('http://httpbin.org/ip') as res:
print('Status:', res.status)
print('Headers:', res.headers)
print('Body:', await res.text())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
Featured JSON body matching¶
import json
import pook
import requests
# Enable mock engine
pook.on()
(pook.post('httpbin.org/post')
.json({'foo': 'bar'})
.reply(204)
.json({'error': 'simulated'}))
res = requests.post('http://httpbin.org/post',
data=json.dumps({'foo': 'bar'}))
print('Status:', res.status_code)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
JSONSchema based body matching¶
import json
import pook
import requests
schema = {
'type': 'object',
'properties': {
'foo': {'type': 'string'},
}
}
# Enable mock engine
pook.on()
(pook.post('httpbin.org/post')
.jsonschema(schema)
.reply(204)
.json({'error': 'simulated'}))
res = requests.post('http://httpbin.org/post',
data=json.dumps({'foo': 'bar'}))
print('Status:', res.status_code)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
Enable real networking mode¶
import pook
import requests
# Enable mock engine
pook.on()
# Enable network mode
pook.enable_network()
(pook.get('httpbin.org/headers')
.reply(204)
.headers({'server': 'pook'})
.json({'error': 'simulated'}))
res = requests.get('http://httpbin.org/headers')
print('Mock status:', res.status_code)
# Real network request, since pook cannot match any mock
res = requests.get('http://httpbin.org/ip')
print('Real status:', res.status_code)
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
# Disable network mode once we're done
pook.disable_network()
Persistent mock¶
import pook
import requests
# Enable mock engine
pook.on()
(pook.get('httpbin.org')
.headers({'Client': 'requests'})
.persist()
.reply(400)
.headers({'server': 'pook'})
.json({'error': 'simulated'}))
res = requests.get('http://httpbin.org',
headers={'Client': 'requests'})
print('Status:', res.status_code)
print('Headers:', res.headers)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
Time TTL limited mock¶
import pook
import requests
# Enable mock engine
pook.on()
# Declare mock
(pook.get('httpbin.org')
.times(2)
.reply(400)
.headers({'server': 'pook'})
.json({'error': 'simulated'}))
# Mock request 1
res = requests.get('http://httpbin.org')
print('#1 status:', res.status_code)
print('#1 body:', res.json())
# Mock request 2
res = requests.get('http://httpbin.org')
print('#2 status:', res.status_code)
print('#2 body:', res.json())
# Real request 3
try:
requests.get('http://httpbin.org')
except Exception:
print('Request #3 not matched due to expired mock')
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
Regular expression matching¶
import pook
import requests
# Enable mock engine
pook.on()
# Mock definition based
(pook.get(pook.regex('h[t]{2}pbin.*'))
.path(pook.regex('/foo/[a-z]+/baz'))
.header('Client', pook.regex('requests|pook'))
.times(2)
.reply(200)
.headers({'server': 'pook'})
.json({'foo': 'bar'}))
# Perform request
res = requests.get('http://httpbin.org/foo/bar/baz',
headers={'Client': 'requests'})
print('Status:', res.status_code)
print('Body:', res.json())
# Perform second request
res = requests.get('http://httpbin.org/foo/foo/baz',
headers={'Client': 'pook'})
print('Status:', res.status_code)
print('Body:', res.json())
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
unittest
integration¶
import pook
import unittest
import requests
class TestUnitTestEngine(unittest.TestCase):
@pook.on
def test_request(self):
pook.get('server.com/foo').reply(204)
res = requests.get('http://server.com/foo')
self.assertEqual(res.status_code, 204)
def test_request_with_context_manager(self):
with pook.use():
pook.get('server.com/bar', reply=204)
res = requests.get('http://server.com/bar')
self.assertEqual(res.status_code, 204)
@pook.on
def test_no_match_exception(self):
pook.get('server.com/bar', reply=204)
try:
requests.get('http://server.com/baz')
except Exception:
pass
else:
raise RuntimeError('expected to fail')
py.test
integration¶
# -*- coding: utf-8 -*-
import pook
import pytest
import requests
@pook.activate
def test_simple_pook_request():
pook.get('server.com/foo').reply(204)
res = requests.get('http://server.com/foo')
assert res.status_code == 204
@pook.on
def test_enable_engine():
pook.get('server.com/foo').reply(204)
res = requests.get('http://server.com/foo')
assert res.status_code == 204
pook.disable()
@pook.get('server.com/bar', reply=204)
def test_decorator():
res = requests.get('http://server.com/bar')
assert res.status_code == 204
def test_context_manager():
with pook.use():
pook.get('server.com/baz', reply=204)
res = requests.get('http://server.com/baz')
assert res.status_code == 204
@pook.on
def test_no_match_exception():
pook.get('server.com/bar', reply=204)
with pytest.raises(Exception):
requests.get('http://server.com/baz')
Simulated error exception on mock matching¶
import pook
import requests
# Enable mock engine
pook.on()
# Simulated error exception on request matching
pook.get('httpbin.org/status/500', error=Exception('simulated error'))
try:
requests.get('http://httpbin.org/status/500')
except Exception as err:
print('Error:', err)
Using urllib3
as HTTP client¶
import pook
import urllib3
# Mock HTTP traffic only in the given context
with pook.use():
pook.get('http://httpbin.org/status/404').reply(204)
# Intercept request
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/status/404')
print('#1 status:', r.status)
# Real request outside of the context manager
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/status/404')
print('#2 status:', r.status)
Asynchronous HTTP request using aiohttp
¶
# flake8: noqa
import pook
import aiohttp
import asyncio
import async_timeout
async def fetch(session, url, data):
with async_timeout.timeout(10):
async with session.get(url, data=data) as res:
print('Status:', res.status)
print('Headers:', res.headers)
print('Body:', await res.text())
with pook.use(network=True):
pook.get('http://httpbin.org/ip',
reply=404, response_type='json',
response_headers={'Server': 'nginx'},
response_json={'error': 'not found'})
async def main(loop):
async with aiohttp.ClientSession(loop=loop) as session:
await fetch(session, 'http://httpbin.org/ip',
bytearray('foo bar', 'utf-8'))
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
Using http.client
standard Python package as HTTP client¶
import http.client
import pook
# Enable mock engine
pook.on()
mock = pook.get('http://httpbin.org/ip',
reply=404, response_type='json',
response_json={'error': 'not found'})
conn = http.client.HTTPConnection('httpbin.org')
conn.request('GET', '/ip')
res = conn.getresponse()
print('Status:', res.status, res.reason)
print('Headers:', res.headers)
print('Body:', res.read())
print('Mock calls:', mock.calls)
print('Is done:', pook.isdone())
print('Pending mocks:', pook.pending_mocks())
print('Unmatched requests:', pook.unmatched_requests())
Example using mocket Python library as underlying mock engine¶
# Be sure you have `mocket` installed:
# $ pip install mocket
import pook
import requests
from mocket.plugins.pook_mock_engine import MocketEngine
# Use mocket library as underlying mock engine
pook.set_mock_engine(MocketEngine)
# Explicitly enable pook HTTP mocking (required)
pook.on()
# Target server URL to mock out
url = 'http://twitter.com/api/1/foobar'
# Define your mock
mock = pook.get(url,
reply=404, times=2,
headers={'content-type': 'application/json'},
response_json={'error': 'foo'})
# Run first HTTP request
requests.get(url)
assert mock.calls == 1
# Run second HTTP request
res = requests.get(url)
assert mock.calls == 2
# Assert response data
assert res.status_code == 404
assert res.json() == {'error': 'foo'}
# Explicitly disable pook (optional)
pook.off()
Hy programming language example¶
(import [pook])
(import [requests])
(defn request [url &optional [status 404]]
(doto (.mock pook url) (.reply status))
(let [res (.get requests url)]
(. res status_code)))
(defn run []
(with [(.use pook)]
(print "Status:" (request "http://foo.com/bar" :status 204))))
;; Run test program
(defmain [&args] (run))