From baf6adbfef61a39ea812cfe0d8a77e54144e850d Mon Sep 17 00:00:00 2001 From: Miguel Araujo Perez Date: Mon, 16 Sep 2013 12:47:13 +0200 Subject: [PATCH 1/2] Added expected_data parameter to register_uri This checks that POST payload received matches the one expected. This is very helpful for improving robustness of some mocked tests. --- httpretty/core.py | 14 ++++++++-- tests/functional/test_requests.py | 31 +++++++++++++++++++++ tests/functional/test_urllib2.py | 45 +++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/httpretty/core.py b/httpretty/core.py index d456fb18..1af2746f 100644 --- a/httpretty/core.py +++ b/httpretty/core.py @@ -25,6 +25,7 @@ # OTHER DEALINGS IN THE SOFTWARE. from __future__ import unicode_literals +from urlparse import parse_qsl import re import inspect import socket @@ -277,6 +278,13 @@ def sendall(self, data, *args, **kw): for matcher, value in httpretty._entries.items(): if matcher.matches(info): + if matcher.expected_data is not None: + body_dict = dict(parse_qsl(request.body)) + if body_dict != matcher.expected_data: + raise ValueError("Body Post didn't match, expected %s, got %s" % ( + matcher.expected_data, + body_dict + )) entries = value break @@ -601,12 +609,13 @@ class URIMatcher(object): regex = None info = None - def __init__(self, uri, entries): + def __init__(self, uri, expected_data, entries): if type(uri).__name__ == 'SRE_Pattern': self.regex = uri else: self.info = URIInfo.from_uri(uri, entries) + self.expected_data = expected_data self.entries = entries #hash of current_entry pointers, per method. @@ -683,6 +692,7 @@ def register_uri(cls, method, uri, body='HTTPretty :)', adding_headers=None, forcing_headers=None, status=200, + expected_data=None, responses=None, **headers): uri_is_string = isinstance(uri, basestring) @@ -705,7 +715,7 @@ def register_uri(cls, method, uri, body='HTTPretty :)', cls.Response(method=method, uri=uri, **headers), ] - matcher = URIMatcher(uri, entries_for_this_uri) + matcher = URIMatcher(uri, expected_data, entries_for_this_uri) if matcher in cls._entries: matcher.entries.extend(cls._entries[matcher]) del cls._entries[matcher] diff --git a/tests/functional/test_requests.py b/tests/functional/test_requests.py index 930ec281..67a9855e 100644 --- a/tests/functional/test_requests.py +++ b/tests/functional/test_requests.py @@ -626,3 +626,34 @@ def test_lack_of_trailing_slash(): HTTPretty.register_uri(HTTPretty.GET, url, body='') response = requests.get(url) response.status_code.should.equal(200) + + +@httprettified +def test_httpretty_should_check_post_payload(): + "HTTPretty should allow checking POST data payload" + + HTTPretty.register_uri( + HTTPretty.POST, + "https://api.imaginary.com/v1/sweet/", + expected_data={'name': "Lollipop"}, + body='{"id": 12, "status": "Created"}', + ) + + response = requests.post( + "https://api.imaginary.com/v1/sweet/", + {"name": "Lollipop"} + ) + + expect(HTTPretty.last_request.method).to.equal('POST') + expect(HTTPretty.last_request.method).to.equal('POST') + expect(HTTPretty.last_request.body).to.equal(b'name=Lollipop') + expect(response.json()).to.equal({"id": 12, "status": "Created"}) + + try: + response = requests.post( + "https://api.imaginary.com/v1/sweet/", + {"wrong": "data"} + ) + raise Exception("Payload checked didn't work") + except ValueError: + pass diff --git a/tests/functional/test_urllib2.py b/tests/functional/test_urllib2.py index cb84f000..d341b1ae 100644 --- a/tests/functional/test_urllib2.py +++ b/tests/functional/test_urllib2.py @@ -27,6 +27,7 @@ from __future__ import unicode_literals try: + from urllib import urlencode from urllib.request import urlopen import urllib.request as urllib2 except ImportError: @@ -335,3 +336,47 @@ def test_httpretty_should_allow_registering_regexes(): fd.close() expect(got).to.equal(b"Found brand") + + +@httprettified +def test_httpretty_should_check_post_payload(): + "HTTPretty should allow checking POST data payload" + + HTTPretty.register_uri( + HTTPretty.POST, + "https://api.imaginary.com/v1/sweet/", + expected_data={'name': "Lollipop"}, + body='{"id": 12, "status": "Created"}', + ) + + request = urllib2.Request( + "https://api.imaginary.com/v1/sweet/", + urlencode({"name": "Lollipop"}), + { + 'content-type': 'text/json', + }, + ) + fd = urllib2.urlopen(request) + got = fd.read() + fd.close() + + expect(HTTPretty.last_request.method).to.equal('POST') + expect(HTTPretty.last_request.method).to.equal('POST') + expect(HTTPretty.last_request.body).to.equal(b'name=Lollipop') + expect(got).to.equal(b'{"id": 12, "status": "Created"}') + + request = urllib2.Request( + "https://api.imaginary.com/v1/sweet/", + urlencode({"wrong": "data"}), + { + 'content-type': 'text/json', + }, + ) + + try: + fd = urllib2.urlopen(request) + got = fd.read() + fd.close() + raise Exception("Payload checked didn't work") + except ValueError: + pass From 2f86ef83c55d8218dc8cfa148b73a3e3487961b8 Mon Sep 17 00:00:00 2001 From: Miguel Araujo Perez Date: Tue, 22 Oct 2013 18:17:49 +0200 Subject: [PATCH 2/2] Polishing expected data --- httpretty/core.py | 17 ++++++++++------- tests/functional/test_requests.py | 12 ++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/httpretty/core.py b/httpretty/core.py index 1af2746f..ac48b0b5 100644 --- a/httpretty/core.py +++ b/httpretty/core.py @@ -278,13 +278,7 @@ def sendall(self, data, *args, **kw): for matcher, value in httpretty._entries.items(): if matcher.matches(info): - if matcher.expected_data is not None: - body_dict = dict(parse_qsl(request.body)) - if body_dict != matcher.expected_data: - raise ValueError("Body Post didn't match, expected %s, got %s" % ( - matcher.expected_data, - body_dict - )) + matcher.check_expected_data(request) entries = value break @@ -627,6 +621,15 @@ def matches(self, info): else: return self.regex.search(info.full_url(use_querystring=False)) + def check_expected_data(self, request): + if self.expected_data is not None: + body_dict = dict(parse_qsl(request.body)) + if body_dict != self.expected_data: + raise ValueError("Body Post didn't match, expected %s, got %s" % ( + self.expected_data, + body_dict + )) + def __str__(self): wrap = 'URLMatcher({0})' if self.info: diff --git a/tests/functional/test_requests.py b/tests/functional/test_requests.py index 67a9855e..368ac937 100644 --- a/tests/functional/test_requests.py +++ b/tests/functional/test_requests.py @@ -649,11 +649,7 @@ def test_httpretty_should_check_post_payload(): expect(HTTPretty.last_request.body).to.equal(b'name=Lollipop') expect(response.json()).to.equal({"id": 12, "status": "Created"}) - try: - response = requests.post( - "https://api.imaginary.com/v1/sweet/", - {"wrong": "data"} - ) - raise Exception("Payload checked didn't work") - except ValueError: - pass + requests.post.when.called_with( + "https://api.imaginary.com/v1/sweet/", + {'wrong': 'data'} + ).should.throw(ValueError)