Skip to content

Commit c085a01

Browse files
Merge pull request #26 from AnObfuscator/stub-multiple-requests
Fixes #25: support for stubbing multiple requests at the same time
2 parents 7683f35 + 22c0272 commit c085a01

File tree

3 files changed

+102
-43
lines changed

3 files changed

+102
-43
lines changed

e2e/contracts/test_e2e.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,36 @@ def test_post_user_complex(self):
5757

5858
self.assertEqual(result.json(), expected)
5959

60+
def test_multiple_exact_matches(self):
61+
expected = {'name': 'Jonas'}
62+
(pact
63+
.given('a simple json blob exists')
64+
.upon_receiving('a request for a user')
65+
.with_request('get', '/users/Jonas')
66+
.will_respond_with(200, body=expected)
67+
.given('a complex json blob exists')
68+
.upon_receiving('a query for the user Jonas')
69+
.with_request(
70+
'post',
71+
'/users/',
72+
body={'kind': 'name'},
73+
headers={'Accept': 'application/json'},
74+
query='Jonas')
75+
.will_respond_with(
76+
200,
77+
body=expected,
78+
headers={'Content-Type': 'application/json'}))
79+
80+
with pact:
81+
result_get = requests.get('http://localhost:1234/users/Jonas')
82+
result_post = requests.post(
83+
'http://localhost:1234/users/?Jonas',
84+
headers={'Accept': 'application/json'},
85+
json={'kind': 'name'})
86+
87+
self.assertEqual(result_get.json(), expected)
88+
self.assertEqual(result_post.json(), expected)
89+
6090

6191
class InexactMatches(BaseTestCase):
6292
def test_sparse(self):

pact/pact.py

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""API for creating a contract and configuring the mock service."""
22
from __future__ import unicode_literals
3+
34
import os
45
from subprocess import Popen
56

@@ -85,11 +86,7 @@ def __init__(self, consumer, provider, host_name='localhost', port=1234,
8586
self.sslcert = sslcert
8687
self.sslkey = sslkey
8788
self.version = version
88-
self._description = None
89-
self._provider_state = None
90-
self._request = None
91-
self._response = None
92-
self._scenario = None
89+
self._interactions = []
9390

9491
def given(self, provider_state):
9592
"""
@@ -103,26 +100,20 @@ def given(self, provider_state):
103100
:type provider_state: basestring
104101
:rtype: Pact
105102
"""
106-
self._provider_state = provider_state
103+
self._interactions.insert(0, {'provider_state': provider_state})
107104
return self
108105

109106
def setup(self):
110107
"""Configure the Mock Service to ready it for a test."""
111108
try:
112-
payload = {
113-
'description': self._description,
114-
'provider_state': self._provider_state,
115-
'request': self._request,
116-
'response': self._response
117-
}
118-
119109
resp = requests.delete(
120110
self.uri + '/interactions', headers=self.HEADERS)
121111

122112
assert resp.status_code == 200, resp.content
123-
resp = requests.post(
113+
resp = requests.put(
124114
self.uri + '/interactions',
125-
headers=self.HEADERS, json=payload)
115+
headers=self.HEADERS,
116+
json={"interactions": self._interactions})
126117

127118
assert resp.status_code == 200, resp.content
128119
except AssertionError:
@@ -170,7 +161,7 @@ def upon_receiving(self, scenario):
170161
:type scenario: basestring
171162
:rtype: Pact
172163
"""
173-
self._description = scenario
164+
self._interactions[0]['description'] = scenario
174165
return self
175166

176167
def verify(self):
@@ -182,6 +173,7 @@ def verify(self):
182173
183174
:raises AssertionError: When not all interactions are found.
184175
"""
176+
self._interactions = []
185177
resp = requests.get(
186178
self.uri + '/interactions/verification',
187179
headers=self.HEADERS)
@@ -215,9 +207,8 @@ def with_request(self, method, path, body=None, headers=None, query=None):
215207
:type query: dict, basestring, or None
216208
:rtype: Pact
217209
"""
218-
self._request = Request(
210+
self._interactions[0]['request'] = Request(
219211
method, path, body=body, headers=headers, query=query).json()
220-
221212
return self
222213

223214
def will_respond_with(self, status, headers=None, body=None):
@@ -233,7 +224,9 @@ def will_respond_with(self, status, headers=None, body=None):
233224
:type body: Matcher, dict, list, basestring, or None
234225
:rtype: Pact
235226
"""
236-
self._response = Response(status, headers=headers, body=body).json()
227+
self._interactions[0]['response'] = Response(status,
228+
headers=headers,
229+
body=body).json()
237230
return self
238231

239232
def __enter__(self):

pact/test/test_pact.py

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,7 @@ def test_init_defaults(self):
2727
self.assertIsNone(target.sslkey)
2828
self.assertEqual(target.uri, 'http://localhost:1234')
2929
self.assertEqual(target.version, '2.0.0')
30-
self.assertIsNone(target._description)
31-
self.assertIsNone(target._provider_state)
32-
self.assertIsNone(target._request)
33-
self.assertIsNone(target._response)
34-
self.assertIsNone(target._scenario)
30+
self.assertEqual(len(target._interactions), 0)
3531

3632
def test_init_custom_mock_service(self):
3733
target = Pact(
@@ -51,11 +47,7 @@ def test_init_custom_mock_service(self):
5147
self.assertEqual(target.sslkey, '/ssl.pem')
5248
self.assertEqual(target.uri, 'https://192.168.1.1:8000')
5349
self.assertEqual(target.version, '3.0.0')
54-
self.assertIsNone(target._description)
55-
self.assertIsNone(target._provider_state)
56-
self.assertIsNone(target._request)
57-
self.assertIsNone(target._response)
58-
self.assertIsNone(target._scenario)
50+
self.assertEqual(len(target._interactions), 0)
5951

6052
def test_definition_sparse(self):
6153
target = Pact(self.consumer, self.provider)
@@ -65,15 +57,20 @@ def test_definition_sparse(self):
6557
.with_request('GET', '/path')
6658
.will_respond_with(200, body='success'))
6759

60+
self.assertEqual(len(target._interactions), 1)
61+
6862
self.assertEqual(
69-
target._provider_state,
63+
target._interactions[0]['provider_state'],
7064
'I am creating a new pact using the Pact class')
7165

7266
self.assertEqual(
73-
target._description, 'a specific request to the server')
67+
target._interactions[0]['description'],
68+
'a specific request to the server')
7469

75-
self.assertEqual(target._request, {'path': '/path', 'method': 'GET'})
76-
self.assertEqual(target._response, {'status': 200, 'body': 'success'})
70+
self.assertEqual(target._interactions[0]['request'],
71+
{'path': '/path', 'method': 'GET'})
72+
self.assertEqual(target._interactions[0]['response'],
73+
{'status': 200, 'body': 'success'})
7774

7875
def test_definition_all_options(self):
7976
target = Pact(self.consumer, self.provider)
@@ -89,23 +86,62 @@ def test_definition_all_options(self):
8986
body='success', headers={'Content-Type': 'application/json'}))
9087

9188
self.assertEqual(
92-
target._provider_state,
89+
target._interactions[0]['provider_state'],
9390
'I am creating a new pact using the Pact class')
9491

9592
self.assertEqual(
96-
target._description, 'a specific request to the server')
93+
target._interactions[0]['description'],
94+
'a specific request to the server')
9795

98-
self.assertEqual(target._request, {
96+
self.assertEqual(target._interactions[0]['request'], {
9997
'path': '/path',
10098
'method': 'GET',
10199
'body': {'key': 'value'},
102100
'headers': {'Accept': 'application/json'},
103101
'query': {'search': 'test'}})
104-
self.assertEqual(target._response, {
102+
self.assertEqual(target._interactions[0]['response'], {
105103
'status': 200,
106104
'body': 'success',
107105
'headers': {'Content-Type': 'application/json'}})
108106

107+
def test_definition_multiple_interactions(self):
108+
target = Pact(self.consumer, self.provider)
109+
(target
110+
.given('I am creating a new pact using the Pact class')
111+
.upon_receiving('a specific request to the server')
112+
.with_request('GET', '/foo')
113+
.will_respond_with(200, body='success')
114+
.given('I am creating another new pact using the Pact class')
115+
.upon_receiving('a different request to the server')
116+
.with_request('GET', '/bar')
117+
.will_respond_with(200, body='success'))
118+
119+
self.assertEqual(len(target._interactions), 2)
120+
121+
self.assertEqual(
122+
target._interactions[1]['provider_state'],
123+
'I am creating a new pact using the Pact class')
124+
self.assertEqual(
125+
target._interactions[0]['provider_state'],
126+
'I am creating another new pact using the Pact class')
127+
128+
self.assertEqual(
129+
target._interactions[1]['description'],
130+
'a specific request to the server')
131+
self.assertEqual(
132+
target._interactions[0]['description'],
133+
'a different request to the server')
134+
135+
self.assertEqual(target._interactions[1]['request'],
136+
{'path': '/foo', 'method': 'GET'})
137+
self.assertEqual(target._interactions[0]['request'],
138+
{'path': '/bar', 'method': 'GET'})
139+
140+
self.assertEqual(target._interactions[1]['response'],
141+
{'status': 200, 'body': 'success'})
142+
self.assertEqual(target._interactions[0]['response'],
143+
{'status': 200, 'body': 'success'})
144+
109145

110146
class PactSetupTestCase(PactTestCase):
111147
def setUp(self):
@@ -122,16 +158,16 @@ def setUp(self):
122158
self.delete_call = call('delete', 'http://localhost:1234/interactions',
123159
headers={'X-Pact-Mock-Service': 'true'})
124160

125-
self.post_interactions_call = call(
126-
'post', 'http://localhost:1234/interactions',
161+
self.put_interactions_call = call(
162+
'put', 'http://localhost:1234/interactions',
127163
data=None,
128164
headers={'X-Pact-Mock-Service': 'true'},
129-
json={
165+
json={'interactions': [{
130166
'response': {'status': 200, 'body': 'success'},
131167
'request': {'path': '/path', 'method': 'GET'},
132168
'description': 'a specific request to the server',
133169
'provider_state': 'I am creating a new pact using the '
134-
'Pact class'})
170+
'Pact class'}]})
135171

136172
def test_error_deleting_interactions(self):
137173
self.mock_requests.side_effect = iter([
@@ -155,15 +191,15 @@ def test_error_posting_interactions(self):
155191
self.assertEqual(str(e.exception), 'post interactions error')
156192
self.assertEqual(self.mock_requests.call_count, 2)
157193
self.mock_requests.assert_has_calls(
158-
[self.delete_call, self.post_interactions_call])
194+
[self.delete_call, self.put_interactions_call])
159195

160196
def test_successful(self):
161197
self.mock_requests.side_effect = iter([Mock(status_code=200)] * 4)
162198
self.target.setup()
163199

164200
self.assertEqual(self.mock_requests.call_count, 2)
165201
self.mock_requests.assert_has_calls([
166-
self.delete_call, self.post_interactions_call])
202+
self.delete_call, self.put_interactions_call])
167203

168204

169205
class PactStartShutdownServerTestCase(TestCase):

0 commit comments

Comments
 (0)