Skip to content

Commit 72684a4

Browse files
committed
Add checks for request body and method.
1 parent c13a464 commit 72684a4

File tree

3 files changed

+106
-21
lines changed

3 files changed

+106
-21
lines changed

abe/mocks.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,11 @@
55

66
class AbeMock(object):
77

8-
def __init__(self, filename):
8+
def __init__(self, data):
99
"""
1010
Initialise an ABE mock from data.
1111
12-
filename is expected to be the path to an ABE file.
13-
1412
"""
15-
with open(filename, 'r') as f:
16-
data = json.load(f)
17-
1813
# map JSON fields to attributes
1914
self.__dict__ = data
2015

@@ -25,6 +20,18 @@ def __init__(self, filename):
2520
self._feed_inherited_fields(value, 'request', ['url', 'method'])
2621
self.examples[key] = dotify(value)
2722

23+
@classmethod
24+
def from_filename(cls, filename):
25+
"""
26+
Initialise an ABE mock from a spec file.
27+
28+
filename is expected to be the path to an ABE file.
29+
30+
"""
31+
with open(filename, 'r') as f:
32+
data = json.load(f)
33+
return AbeMock(data)
34+
2835
def _feed_inherited_fields(self, value, where, inheritable):
2936
"""
3037
If missing in request or response, some fields are inherited.

abe/unittest.py

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ def load_sample(self, sample_path):
2121
"""
2222
Load a sample file into an AbeMock object.
2323
"""
24-
sample_file = os.path.join(self.samples_root, sample_path)
25-
return AbeMock(sample_file)
24+
sample_filename = os.path.join(self.samples_root, sample_path)
25+
return AbeMock.from_filename(sample_filename)
2626

2727
def get_sample_request(self, path, label):
2828
"""
@@ -107,16 +107,39 @@ def assert_headers_contain(self, response_data, spec_data):
107107
"header {0}".format(expected_header)
108108
)
109109

110-
def assert_matches_sample(self, path, label, url, response):
110+
def assert_matches_request(self, sample_request, wsgi_request):
111+
"""
112+
Check that the sample request and wsgi request match.
113+
"""
114+
self.assertEqual(wsgi_request.META['PATH_INFO'], sample_request['url'])
115+
self.assertEqual(wsgi_request.META['REQUEST_METHOD'],
116+
sample_request['method'])
117+
118+
if 'headers' in sample_request:
119+
self.assert_headers_contain(
120+
wsgi_request.META, sample_request['headers']
121+
)
122+
123+
if 'body' in sample_request:
124+
self.assert_data_equal(wsgi_request.POST, sample_request['body'])
125+
126+
def assert_matches_response(self, sample_response, wsgi_response):
127+
"""
128+
Check that the sample response and wsgi response match.
129+
"""
130+
self.assertEqual(wsgi_response.status_code, sample_response.status)
131+
if 'body' in sample_response:
132+
response_parsed = wsgi_response.data
133+
self.assert_data_equal(response_parsed, sample_response.body)
134+
135+
def assert_matches_sample(self, path, label, response):
111136
"""
112137
Check a URL and response against a sample.
113138
114139
:param sample_name:
115140
The name of the sample file, e.g. 'query.json'
116141
:param label:
117142
The label for a specific sample request/response, e.g. 'OK'
118-
:param url:
119-
The actual URL we want to compare with the sample
120143
:param response:
121144
The actual API response we want to match with the sample.
122145
It is assumed to be a Django Rest Framework response object
@@ -125,13 +148,5 @@ def assert_matches_sample(self, path, label, url, response):
125148
sample_request = sample.examples[label].request
126149
sample_response = sample.examples[label].response
127150

128-
self.assertEqual(url, sample_request.url)
129-
if 'headers' in sample_request:
130-
self.assert_headers_contain(
131-
response.request, sample_request.headers
132-
)
133-
134-
self.assertEqual(response.status_code, sample_response.status)
135-
if 'body' in sample_response:
136-
response_parsed = response.data
137-
self.assert_data_equal(response_parsed, sample_response.body)
151+
self.assert_matches_response(sample_response, response)
152+
self.assert_matches_request(sample_request, response.wsgi_request)

tests/test_assertions.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from unittest import TestCase
2+
from mock import Mock
23

4+
from abe.mocks import AbeMock
35
from abe.unittest import AbeTestMixin
46

57

@@ -71,3 +73,64 @@ def test_requires_key_and_value_match(self):
7173
{'HTTP_THIS_CUSTOM': 'Foo'},
7274
{'This-Custom-Header': 'Foo'},
7375
)
76+
77+
78+
class TestAssertMatchesRequest(TestCase, AbeTestMixin):
79+
80+
def setUp(self):
81+
abe_mock = AbeMock({
82+
"method": "POST",
83+
"url": "/resource/",
84+
"examples": {
85+
"OK": {
86+
"request": {
87+
"queryParams": {},
88+
"body": {
89+
"name": "My Resource"
90+
},
91+
"headers": {
92+
"This-Custom-Header": 'Foo'
93+
}
94+
}
95+
}
96+
}
97+
})
98+
self.sample_request = abe_mock.examples['OK'].request
99+
100+
self.mock_wsgi_request = Mock(
101+
POST={'name': 'My Resource'},
102+
META={
103+
'HTTP_THIS_CUSTOM_HEADER': 'Foo',
104+
'REQUEST_METHOD': 'POST',
105+
'PATH_INFO': '/resource/'
106+
},
107+
)
108+
109+
def test_success_case(self):
110+
self.assert_matches_request(
111+
self.sample_request, self.mock_wsgi_request
112+
)
113+
114+
def test_assertion_error_if_url_mismatch(self):
115+
self.mock_wsgi_request.META['PATH_INFO'] = '/resourceoops/'
116+
117+
with self.assertRaises(AssertionError):
118+
self.assert_matches_request(
119+
self.sample_request, self.mock_wsgi_request
120+
)
121+
122+
def test_assertion_error_if_method_mismatch(self):
123+
self.mock_wsgi_request.META['REQUEST_METHOD'] = 'PATCH'
124+
125+
with self.assertRaises(AssertionError):
126+
self.assert_matches_request(
127+
self.sample_request, self.mock_wsgi_request
128+
)
129+
130+
def test_assertion_error_if_post_data_mismatch(self):
131+
self.mock_wsgi_request.POST = {'a': 1}
132+
133+
with self.assertRaises(AssertionError):
134+
self.assert_matches_request(
135+
self.sample_request, self.mock_wsgi_request
136+
)

0 commit comments

Comments
 (0)