Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
.*.sw[po]
dist/
*.egg-info
*.egg
*.egg/
*.egg*
doc/__build/*
docs/_build/
build/
Expand Down
14 changes: 14 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,20 @@ Let's fire our example test::

$ py.test example.py

Example of how to fake a socket errors
======================================

It's very important that we test non-happy paths.

.. code-block:: python

@mocketize
def test_raise_exception(self):
url = "http://github.com/fluidicon.png"
Entry.single_register(Entry.GET, url, exception=socket.error())
with self.assertRaises(requests.exceptions.ConnectionError):
requests.get(url)

Example of how to record real socket traffic
============================================

Expand Down
2 changes: 1 addition & 1 deletion mocket/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@

__all__ = ("mocketize", "Mocket", "MocketEntry", "Mocketizer")

__version__ = "3.9.1"
__version__ = "3.9.2"
22 changes: 16 additions & 6 deletions mocket/mocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@ def enable(namespace=None, truesocket_recording_dir=None):
(2, 1, 6, "", (host, port))
]
ssl.wrap_socket = ssl.__dict__["wrap_socket"] = FakeSSLContext.wrap_socket
# ssl.SSLSocket = ssl.__dict__["SSLSocket"] = MocketSocket
ssl.SSLContext = ssl.__dict__["SSLContext"] = FakeSSLContext
socket.inet_pton = socket.__dict__["inet_pton"] = lambda family, ip: byte_type(
"\x7f\x00\x00\x01", "utf-8"
Expand Down Expand Up @@ -502,7 +501,6 @@ def disable():
socket.gethostbyname = socket.__dict__["gethostbyname"] = true_gethostbyname
socket.getaddrinfo = socket.__dict__["getaddrinfo"] = true_getaddrinfo
ssl.wrap_socket = ssl.__dict__["wrap_socket"] = true_ssl_wrap_socket
# ssl.SSLSocket = ssl.__dict__["SSLSocket"] = true_ssl_socket
ssl.SSLContext = ssl.__dict__["SSLContext"] = true_ssl_context
socket.inet_pton = socket.__dict__["inet_pton"] = true_inet_pton
urllib3.util.ssl_.wrap_socket = urllib3.util.ssl_.__dict__[
Expand Down Expand Up @@ -548,7 +546,9 @@ def __init__(self, location, responses):

lresponses = []
for r in responses:
if not getattr(r, "data", False):
if isinstance(r, BaseException):
pass
elif not getattr(r, "data", False):
if isinstance(r, text_type):
r = encode_to_bytes(r)
r = self.response_cls(r)
Expand All @@ -569,6 +569,10 @@ def get_response(self):
response = self.responses[self.response_index]
if self.response_index < len(self.responses) - 1:
self.response_index += 1

if isinstance(response, BaseException):
raise response

return response.data


Expand Down Expand Up @@ -600,9 +604,15 @@ def check_and_call(self, method):
def wrap(test=None, truesocket_recording_dir=None):
def wrapper(t, *args, **kw):
instance = args[0] if args else None
namespace = ".".join(
(instance.__class__.__module__, instance.__class__.__name__, t.__name__)
)
namespace = None
if truesocket_recording_dir:
namespace = ".".join(
(
instance.__class__.__module__,
instance.__class__.__name__,
t.__name__,
)
)
with Mocketizer(
instance,
namespace=namespace,
Expand Down
21 changes: 16 additions & 5 deletions mocket/mockhttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,22 @@ def register(cls, method, uri, *responses, **config):

@classmethod
def single_register(
cls, method, uri, body="", status=200, headers=None, match_querystring=True
cls,
method,
uri,
body="",
status=200,
headers=None,
match_querystring=True,
exception=None,
):

response = (
exception
if exception
else cls.response_cls(body=body, status=status, headers=headers)
)

cls.register(
method,
uri,
cls.response_cls(body=body, status=status, headers=headers),
match_querystring=match_querystring,
method, uri, response, match_querystring=match_querystring,
)
45 changes: 27 additions & 18 deletions mocket/mockredis.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from itertools import chain

from .compat import (byte_type, decode_from_bytes, encode_to_bytes, shsplit,
text_type)
from .compat import byte_type, decode_from_bytes, encode_to_bytes, shsplit, text_type
from .mocket import Mocket, MocketEntry


Expand All @@ -21,38 +20,45 @@ class Redisizer(byte_type):
@staticmethod
def tokens(iterable):
iterable = [encode_to_bytes(x) for x in iterable]
return [
'*{0}'.format(len(iterable)).encode('utf-8')
] + list(
chain(*zip(['${0}'.format(len(x)).encode('utf-8') for x in iterable], iterable))
return ["*{0}".format(len(iterable)).encode("utf-8")] + list(
chain(
*zip(
["${0}".format(len(x)).encode("utf-8") for x in iterable], iterable
)
)
)

@staticmethod
def redisize(data):
def get_conversion(t):
return {
dict: lambda x: b'\r\n'.join(Redisizer.tokens(list(chain(*tuple(x.items()))))),
int: lambda x: ':{0}'.format(x).encode('utf-8'),
text_type: lambda x: '${0}\r\n{1}'.format(len(x.encode('utf-8')), x).encode('utf-8'),
list: lambda x: b'\r\n'.join(Redisizer.tokens(x)),
dict: lambda x: b"\r\n".join(
Redisizer.tokens(list(chain(*tuple(x.items()))))
),
int: lambda x: ":{0}".format(x).encode("utf-8"),
text_type: lambda x: "${0}\r\n{1}".format(
len(x.encode("utf-8")), x
).encode("utf-8"),
list: lambda x: b"\r\n".join(Redisizer.tokens(x)),
}[t]

if isinstance(data, Redisizer):
return data
if isinstance(data, byte_type):
data = decode_from_bytes(data)
return Redisizer(get_conversion(data.__class__)(data) + b'\r\n')
return Redisizer(get_conversion(data.__class__)(data) + b"\r\n")

@staticmethod
def command(description, _type='+'):
return Redisizer('{0}{1}{2}'.format(_type, description, '\r\n').encode('utf-8'))
def command(description, _type="+"):
return Redisizer("{0}{1}{2}".format(_type, description, "\r\n").encode("utf-8"))

@staticmethod
def error(description):
return Redisizer.command(description, _type='-')
return Redisizer.command(description, _type="-")


OK = Redisizer.command('OK')
QUEUED = Redisizer.command('QUEUED')
OK = Redisizer.command("OK")
QUEUED = Redisizer.command("QUEUED")
ERROR = Redisizer.error


Expand All @@ -61,7 +67,7 @@ class Entry(MocketEntry):
response_cls = Response

def __init__(self, addr, command, responses):
super(Entry, self).__init__(addr or ('localhost', 6379), responses)
super(Entry, self).__init__(addr or ("localhost", 6379), responses)
d = shsplit(command)
d[0] = d[0].upper()
self.command = Redisizer.tokens(d)
Expand All @@ -71,7 +77,10 @@ def can_handle(self, data):

@classmethod
def register(cls, addr, command, *responses):
responses = [cls.response_cls(r) for r in responses]
responses = [
r if isinstance(r, BaseException) else cls.response_cls(r)
for r in responses
]
Mocket.register(cls(addr, command, responses))

@classmethod
Expand Down
10 changes: 8 additions & 2 deletions tests/main/test_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,13 @@ def test_post_file_object(self):
r = requests.post(url, files=files, data={}, verify=False)
self.assertEqual(r.status_code, 201)

@mocketize
def test_raise_exception(self):
url = "http://github.com/fluidicon.png"
Entry.single_register(Entry.GET, url, exception=socket.error())
with self.assertRaises(requests.exceptions.ConnectionError):
requests.get(url)

@mocketize
def test_sockets(self):
"""
Expand Down Expand Up @@ -355,5 +362,4 @@ def test_sockets(self):
sock.close()

# Proof that worked.
print(Mocket.last_request().__dict__)
assert Mocket.last_request().body == '{"hello": "world"}'
self.assertEqual(Mocket.last_request().body, '{"hello": "world"}')
25 changes: 12 additions & 13 deletions tests/main/test_https.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

import pytest
import requests
from tests import urlopen

from mocket import Mocket, mocketize, Mocketizer
from mocket import Mocket, Mocketizer, mocketize
from mocket.mockhttp import Entry
from tests import urlopen


@pytest.fixture
Expand All @@ -22,18 +22,19 @@ def response():

@mocketize
def test_json(response):
url_to_mock = 'https://testme.org/json'
url_to_mock = "https://testme.org/json"

Entry.single_register(
Entry.GET,
url_to_mock,
body=json.dumps(response),
headers={'content-type': 'application/json'})
headers={"content-type": "application/json"},
)

mocked_response = requests.get(url_to_mock).json()
assert response == mocked_response

mocked_response = json.loads(urlopen(url_to_mock).read().decode('utf-8'))
mocked_response = json.loads(urlopen(url_to_mock).read().decode("utf-8"))
assert response == mocked_response


Expand All @@ -43,29 +44,27 @@ def test_json(response):
@pytest.mark.skipif('os.getenv("SKIP_TRUE_HTTP", False)')
@mocketize(truesocket_recording_dir=recording_directory)
def test_truesendall_with_recording_https():
url = 'https://httpbin.org/ip'
url = "https://httpbin.org/ip"

requests.get(url, headers={"Accept": "application/json"})
resp = requests.get(url, headers={"Accept": "application/json"})
print(resp.content)
assert resp.status_code == 200

dump_filename = os.path.join(
Mocket.get_truesocket_recording_dir(),
Mocket.get_namespace() + '.json',
Mocket.get_truesocket_recording_dir(), Mocket.get_namespace() + ".json",
)
with io.open(dump_filename) as f:
responses = json.load(f)

assert len(responses['httpbin.org']['443'].keys()) == 1
assert len(responses["httpbin.org"]["443"].keys()) == 1


@pytest.mark.skipif('os.getenv("SKIP_TRUE_HTTP", False)')
def test_truesendall_after_mocket_session():
Mocket.enable()
Mocket.disable()

url = 'https://httpbin.org/ip'
url = "https://httpbin.org/ip"
resp = requests.get(url)
assert resp.status_code == 200

Expand All @@ -74,8 +73,8 @@ def test_truesendall_after_mocket_session():
def test_real_request_session():
session = requests.Session()

url1 = 'https://httpbin.org/ip'
url2 = 'http://httpbin.org/headers'
url1 = "https://httpbin.org/ip"
url2 = "http://httpbin.org/headers"

with Mocketizer():
assert len(session.get(url1).content) < len(session.get(url2).content)
Loading