Skip to content

Commit

Permalink
Merge pull request #26 from AnObfuscator/stub-multiple-requests
Browse files Browse the repository at this point in the history
Fixes #25: support for stubbing multiple requests at the same time
  • Loading branch information
matthewbalvanz-wf committed Jun 19, 2017
2 parents 7683f35 + 22c0272 commit c085a01
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 43 deletions.
30 changes: 30 additions & 0 deletions e2e/contracts/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,36 @@ def test_post_user_complex(self):

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

def test_multiple_exact_matches(self):
expected = {'name': 'Jonas'}
(pact
.given('a simple json blob exists')
.upon_receiving('a request for a user')
.with_request('get', '/users/Jonas')
.will_respond_with(200, body=expected)
.given('a complex json blob exists')
.upon_receiving('a query for the user Jonas')
.with_request(
'post',
'/users/',
body={'kind': 'name'},
headers={'Accept': 'application/json'},
query='Jonas')
.will_respond_with(
200,
body=expected,
headers={'Content-Type': 'application/json'}))

with pact:
result_get = requests.get('http://localhost:1234/users/Jonas')
result_post = requests.post(
'http://localhost:1234/users/?Jonas',
headers={'Accept': 'application/json'},
json={'kind': 'name'})

self.assertEqual(result_get.json(), expected)
self.assertEqual(result_post.json(), expected)


class InexactMatches(BaseTestCase):
def test_sparse(self):
Expand Down
31 changes: 12 additions & 19 deletions pact/pact.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""API for creating a contract and configuring the mock service."""
from __future__ import unicode_literals

import os
from subprocess import Popen

Expand Down Expand Up @@ -85,11 +86,7 @@ def __init__(self, consumer, provider, host_name='localhost', port=1234,
self.sslcert = sslcert
self.sslkey = sslkey
self.version = version
self._description = None
self._provider_state = None
self._request = None
self._response = None
self._scenario = None
self._interactions = []

def given(self, provider_state):
"""
Expand All @@ -103,26 +100,20 @@ def given(self, provider_state):
:type provider_state: basestring
:rtype: Pact
"""
self._provider_state = provider_state
self._interactions.insert(0, {'provider_state': provider_state})
return self

def setup(self):
"""Configure the Mock Service to ready it for a test."""
try:
payload = {
'description': self._description,
'provider_state': self._provider_state,
'request': self._request,
'response': self._response
}

resp = requests.delete(
self.uri + '/interactions', headers=self.HEADERS)

assert resp.status_code == 200, resp.content
resp = requests.post(
resp = requests.put(
self.uri + '/interactions',
headers=self.HEADERS, json=payload)
headers=self.HEADERS,
json={"interactions": self._interactions})

assert resp.status_code == 200, resp.content
except AssertionError:
Expand Down Expand Up @@ -170,7 +161,7 @@ def upon_receiving(self, scenario):
:type scenario: basestring
:rtype: Pact
"""
self._description = scenario
self._interactions[0]['description'] = scenario
return self

def verify(self):
Expand All @@ -182,6 +173,7 @@ def verify(self):
:raises AssertionError: When not all interactions are found.
"""
self._interactions = []
resp = requests.get(
self.uri + '/interactions/verification',
headers=self.HEADERS)
Expand Down Expand Up @@ -215,9 +207,8 @@ def with_request(self, method, path, body=None, headers=None, query=None):
:type query: dict, basestring, or None
:rtype: Pact
"""
self._request = Request(
self._interactions[0]['request'] = Request(
method, path, body=body, headers=headers, query=query).json()

return self

def will_respond_with(self, status, headers=None, body=None):
Expand All @@ -233,7 +224,9 @@ def will_respond_with(self, status, headers=None, body=None):
:type body: Matcher, dict, list, basestring, or None
:rtype: Pact
"""
self._response = Response(status, headers=headers, body=body).json()
self._interactions[0]['response'] = Response(status,
headers=headers,
body=body).json()
return self

def __enter__(self):
Expand Down
84 changes: 60 additions & 24 deletions pact/test/test_pact.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ def test_init_defaults(self):
self.assertIsNone(target.sslkey)
self.assertEqual(target.uri, 'http://localhost:1234')
self.assertEqual(target.version, '2.0.0')
self.assertIsNone(target._description)
self.assertIsNone(target._provider_state)
self.assertIsNone(target._request)
self.assertIsNone(target._response)
self.assertIsNone(target._scenario)
self.assertEqual(len(target._interactions), 0)

def test_init_custom_mock_service(self):
target = Pact(
Expand All @@ -51,11 +47,7 @@ def test_init_custom_mock_service(self):
self.assertEqual(target.sslkey, '/ssl.pem')
self.assertEqual(target.uri, 'https://192.168.1.1:8000')
self.assertEqual(target.version, '3.0.0')
self.assertIsNone(target._description)
self.assertIsNone(target._provider_state)
self.assertIsNone(target._request)
self.assertIsNone(target._response)
self.assertIsNone(target._scenario)
self.assertEqual(len(target._interactions), 0)

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

self.assertEqual(len(target._interactions), 1)

self.assertEqual(
target._provider_state,
target._interactions[0]['provider_state'],
'I am creating a new pact using the Pact class')

self.assertEqual(
target._description, 'a specific request to the server')
target._interactions[0]['description'],
'a specific request to the server')

self.assertEqual(target._request, {'path': '/path', 'method': 'GET'})
self.assertEqual(target._response, {'status': 200, 'body': 'success'})
self.assertEqual(target._interactions[0]['request'],
{'path': '/path', 'method': 'GET'})
self.assertEqual(target._interactions[0]['response'],
{'status': 200, 'body': 'success'})

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

self.assertEqual(
target._provider_state,
target._interactions[0]['provider_state'],
'I am creating a new pact using the Pact class')

self.assertEqual(
target._description, 'a specific request to the server')
target._interactions[0]['description'],
'a specific request to the server')

self.assertEqual(target._request, {
self.assertEqual(target._interactions[0]['request'], {
'path': '/path',
'method': 'GET',
'body': {'key': 'value'},
'headers': {'Accept': 'application/json'},
'query': {'search': 'test'}})
self.assertEqual(target._response, {
self.assertEqual(target._interactions[0]['response'], {
'status': 200,
'body': 'success',
'headers': {'Content-Type': 'application/json'}})

def test_definition_multiple_interactions(self):
target = Pact(self.consumer, self.provider)
(target
.given('I am creating a new pact using the Pact class')
.upon_receiving('a specific request to the server')
.with_request('GET', '/foo')
.will_respond_with(200, body='success')
.given('I am creating another new pact using the Pact class')
.upon_receiving('a different request to the server')
.with_request('GET', '/bar')
.will_respond_with(200, body='success'))

self.assertEqual(len(target._interactions), 2)

self.assertEqual(
target._interactions[1]['provider_state'],
'I am creating a new pact using the Pact class')
self.assertEqual(
target._interactions[0]['provider_state'],
'I am creating another new pact using the Pact class')

self.assertEqual(
target._interactions[1]['description'],
'a specific request to the server')
self.assertEqual(
target._interactions[0]['description'],
'a different request to the server')

self.assertEqual(target._interactions[1]['request'],
{'path': '/foo', 'method': 'GET'})
self.assertEqual(target._interactions[0]['request'],
{'path': '/bar', 'method': 'GET'})

self.assertEqual(target._interactions[1]['response'],
{'status': 200, 'body': 'success'})
self.assertEqual(target._interactions[0]['response'],
{'status': 200, 'body': 'success'})


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

self.post_interactions_call = call(
'post', 'http://localhost:1234/interactions',
self.put_interactions_call = call(
'put', 'http://localhost:1234/interactions',
data=None,
headers={'X-Pact-Mock-Service': 'true'},
json={
json={'interactions': [{
'response': {'status': 200, 'body': 'success'},
'request': {'path': '/path', 'method': 'GET'},
'description': 'a specific request to the server',
'provider_state': 'I am creating a new pact using the '
'Pact class'})
'Pact class'}]})

def test_error_deleting_interactions(self):
self.mock_requests.side_effect = iter([
Expand All @@ -155,15 +191,15 @@ def test_error_posting_interactions(self):
self.assertEqual(str(e.exception), 'post interactions error')
self.assertEqual(self.mock_requests.call_count, 2)
self.mock_requests.assert_has_calls(
[self.delete_call, self.post_interactions_call])
[self.delete_call, self.put_interactions_call])

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

self.assertEqual(self.mock_requests.call_count, 2)
self.mock_requests.assert_has_calls([
self.delete_call, self.post_interactions_call])
self.delete_call, self.put_interactions_call])


class PactStartShutdownServerTestCase(TestCase):
Expand Down

0 comments on commit c085a01

Please sign in to comment.