The implement of responses for mocking out the requests
Utility of responses
Basic
import responses
import requests
responses.add(responses.GET,'http://twitter.com/api/1/foobar' ,
json={'error' : 'not found' }, status=404 )
@responses.activate
def test_sample () :
resp = requests.get('http://twitter.com/api/1/foobar' )
assert resp.json() == {"error" : "not found" }
assert resp.status_code = 404
... '''
Multiple responses
import responses
import requests
responses.add(responses.GET,'http://twitter.com/api/1/foobar' ,
status=500 )
responses.add(responses.GET,'http://twitter.com/api/1/foobar' ,
body='{}' , status=200 ,
content_type='application/json' )
@responses.activate
def test_multiple () :
resp = requests.get('http://twitter.com/api/1/foobar' )
assert resp.status_code == 500
resp = requests.get('http://twitter.com/api/1/foobar' )
assert resp.status_code == 200
... '''
Using a callback to modify the response
import responses
import requests
def response_callback (resp) :
resp.callback_processed = True
return resp
with responses.RequestsMock(response_callback=response_callback) as m:
m.add(responses.GET, 'http://example.com' , body=b'test' )
resp = requests.get('http://example.com' )
assert resp.text == "test"
assert hasattr(resp, 'callback_processed' )
assert resp.callback_processed is True
... '''
Structure of responses
RequestMock
方法 作用 _ init _ 初始化 reset 重置 add 添加response add_passthru remove replace add_callback calls _ enter _ 启动mock _ exit _ 恢复 activate wrap testcase() _find_match get response _on_request return response start 启动mock stop 恢复
BaseResponse
方法 作用 _ init _ 初始化 _ eq _ _ ne _ _url_matches_strict _url_matches url -> response get_header get_response matches
Response
方法 作用 _ init _ 初始化 get_response
CallbackResponse
方法 作用 _ init _ 初始化 get_response
Module方法
方法 作用 _is_string _has_unicode _clean_unicode _is_redirect get_wrapped 包装testcase() _ensure_url_default_path _handle_body
How it works
wrap test_example():
Created with Raphaël 2.1.2
test_example()
responses.activate(RequestMock.activate())
get_wrapped()
wrapped_test_example()
execute wrapped_test_example():
Created with Raphaël 2.1.2
wrapped_test_example()
RequestMock.__enter__()
RequestMock.start()
mock.patch()
requests.adapters.HTTPAdapter.send,unbound_on_send()
test_example()
_on_request()
get_response()
Response
get_wrapped():
import inspect
import six
from functools import update_wrapper
_wrapper_template = """\
def wrapper%(signature)s:
with responses:
return func%(funcargs)s
"""
def get_wrapped (func, wrapper_template, evaldict) :
if six.PY2:
args, a, kw, defaults = inspect.getargspec(func)
else :
args, a, kw, defaults, kwonlyargs, kwonlydefaults,
annotations = inspect.getfullargspec(func)
signature = inspect.formatargspec(args, a, kw, defaults)
is_bound_method = hasattr(func, '__self__' )
if is_bound_method:
args = args[1 :]
callargs = inspect.formatargspec(args, a, kw, None )
ctx = {'signature' : signature, 'funcargs' : callargs}
six.exec_(wrapper_template % ctx, evaldict)
wrapper = evaldict['wrapper' ]
update_wrapper(wrapper, func)
if is_bound_method:
wrapper = wrapper.__get__(func.__self__,
type(func.__self__))
return wrapper
... '''
RequestMock.start()
def start (self) :
try :
from unittest import mock
except ImportError:
import mock
def unbound_on_send (adapter, request, *a, **kwargs) :
return self._on_request(adapter, request, *a,
**kwargs)
self._patcher = mock.patch(
'requests.adapters.HTTPAdapter.send' ,
unbound_on_send)
self._patcher.start()
... '''
wrapped_test_example()
def wrapper %(args_signature) s :
with responses:
return test_example%(funcargs)s
... '''
延伸
支持更多HTTP请求框架 :urllib,httplib,aiohttp;支持ORM :SQLAlchemy,peewee。