Use requests-mock for testing

Instead of directly mocking out the HTTPClient use requests-mock to stub
the information that is going over the wire instead of what is being
passed to HTTPClient. This ensures that the HTTPClient is always tested
as well.

Change-Id: I988fb432ced6d4946ab5301ac58fa0d7148bbb79
This commit is contained in:
Jamie Lennox 2016-09-01 14:43:38 +08:00
parent 4388b49328
commit c457718a4d
12 changed files with 293 additions and 364 deletions

@ -12,59 +12,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import mock
from oslotest import base
class FakeResponse(object):
"""Fake response for testing Mistral Client."""
def __init__(self, status_code, content=None):
self.status_code = status_code
self.content = content
self.headers = {}
def json(self):
return json.loads(self.content)
from requests_mock.contrib import fixture
class BaseClientTest(base.BaseTestCase):
_client = None
def mock_http_get(self, content, status_code=200):
if isinstance(content, dict):
content = json.dumps(content)
self._client.http_client.get = mock.MagicMock(
return_value=FakeResponse(status_code, content))
return self._client.http_client.get
def mock_http_post(self, content, status_code=201):
if isinstance(content, dict):
content = json.dumps(content)
self._client.http_client.post = mock.MagicMock(
return_value=FakeResponse(status_code, content))
return self._client.http_client.post
def mock_http_put(self, content, status_code=200):
if isinstance(content, dict):
content = json.dumps(content)
self._client.http_client.put = mock.MagicMock(
return_value=FakeResponse(status_code, content))
return self._client.http_client.put
def mock_http_delete(self, status_code=204):
self._client.http_client.delete = mock.MagicMock(
return_value=FakeResponse(status_code))
return self._client.http_client.delete
def setUp(self):
super(BaseClientTest, self).setUp()
self.requests_mock = self.useFixture(fixture.Fixture())
class BaseCommandTest(base.BaseTestCase):

@ -18,11 +18,14 @@ from mistralclient.tests.unit import base
class BaseClientV2Test(base.BaseClientTest):
TEST_URL = 'http://mistral.example.com'
def setUp(self):
super(BaseClientV2Test, self).setUp()
self._client = client.Client(project_name="test",
mistral_url="test")
mistral_url=self.TEST_URL)
self.workbooks = self._client.workbooks
self.executions = self._client.executions
self.tasks = self._client.tasks

@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from mistralclient.api.v2 import action_executions
from mistralclient.tests.unit.v2 import base
@ -33,7 +31,10 @@ URL_TEMPLATE_ID = '/action_executions/%s'
class TestActionExecutions(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content=ACTION_EXEC)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=ACTION_EXEC,
status_code=201)
body = {
'name': ACTION_EXEC['name']
}
@ -48,10 +49,12 @@ class TestActionExecutions(base.BaseClientV2Test):
self.action_executions, ACTION_EXEC
).to_dict(), action_execution.to_dict())
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(body))
self.assertEqual(body, self.requests_mock.last_request.json())
def test_update(self):
mock = self.mock_http_put(content=ACTION_EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id']
self.requests_mock.put(url, json=ACTION_EXEC)
body = {
'state': ACTION_EXEC['state']
}
@ -73,15 +76,11 @@ class TestActionExecutions(base.BaseClientV2Test):
action_execution.to_dict()
)
mock.assert_called_once_with(
URL_TEMPLATE_ID % ACTION_EXEC['id'],
json.dumps(body)
)
self.assertEqual(body, self.requests_mock.last_request.json())
def test_list(self):
mock = self.mock_http_get(
content={'action_executions': [ACTION_EXEC]}
)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'action_executions': [ACTION_EXEC]})
action_execution_list = self.action_executions.list()
@ -95,10 +94,9 @@ class TestActionExecutions(base.BaseClientV2Test):
self.assertEqual(expected, action_execution.to_dict())
mock.assert_called_once_with(URL_TEMPLATE)
def test_get(self):
mock = self.mock_http_get(content=ACTION_EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id']
self.requests_mock.get(url, json=ACTION_EXEC)
action_execution = self.action_executions.get(ACTION_EXEC['id'])
@ -109,11 +107,8 @@ class TestActionExecutions(base.BaseClientV2Test):
self.assertEqual(expected, action_execution.to_dict())
mock.assert_called_once_with(URL_TEMPLATE_ID % ACTION_EXEC['id'])
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
url = self.TEST_URL + URL_TEMPLATE_ID % ACTION_EXEC['id']
self.requests_mock.delete(url, status_code=204)
self.action_executions.delete(ACTION_EXEC['id'])
mock.assert_called_once_with(URL_TEMPLATE_ID % ACTION_EXEC['id'])

@ -61,21 +61,23 @@ URL_TEMPLATE_VALIDATE = '/actions/validate'
class TestActionsV2(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content={'actions': [ACTION]})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION]},
status_code=201)
actions = self.actions.create(ACTION_DEF)
self.assertIsNotNone(actions)
self.assertEqual(ACTION_DEF, actions[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)
def test_create_with_file(self):
mock = self.mock_http_post(content={'actions': [ACTION]})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION]},
status_code=201)
# The contents of action_v2.yaml must be identical to ACTION_DEF
path = pkg.resource_filename(
@ -88,42 +90,43 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertIsNotNone(actions)
self.assertEqual(ACTION_DEF, actions[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)
def test_update_with_id(self):
mock = self.mock_http_put(content={'actions': [ACTION]})
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_NAME % 123,
json={'actions': [ACTION]})
actions = self.actions.update(ACTION_DEF, id=123)
self.assertIsNotNone(actions)
self.assertEqual(ACTION_DEF, actions[0].definition)
mock.assert_called_once_with(
'/actions/123?scope=private',
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('scope=private', last_request.query)
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)
def test_update(self):
mock = self.mock_http_put(content={'actions': [ACTION]})
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION]})
actions = self.actions.update(ACTION_DEF)
self.assertIsNotNone(actions)
self.assertEqual(ACTION_DEF, actions[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('scope=private', last_request.query)
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)
def test_update_with_file_uri(self):
mock = self.mock_http_put(content={'actions': [ACTION]})
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION]})
# The contents of action_v2.yaml must be identical to ACTION_DEF
path = pkg.resource_filename(
@ -139,14 +142,14 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertIsNotNone(actions)
self.assertEqual(ACTION_DEF, actions[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('scope=private', last_request.query)
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)
def test_list(self):
mock = self.mock_http_get(content={'actions': [ACTION]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION]})
action_list = self.actions.list()
@ -159,12 +162,10 @@ class TestActionsV2(base.BaseClientV2Test):
action.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_list_with_pagination(self):
mock = self.mock_http_get(
content={'actions': [ACTION], 'next': '/actions?fake'}
)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'actions': [ACTION],
'next': '/actions?fake'})
action_list = self.actions.list(
limit=1,
@ -174,13 +175,16 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertEqual(1, len(action_list))
last_request = self.requests_mock.last_request
# The url param order is unpredictable.
self.assertIn('limit=1', mock.call_args[0][0])
self.assertIn('sort_keys=created_at', mock.call_args[0][0])
self.assertIn('sort_dirs=asc', mock.call_args[0][0])
self.assertEqual(['1'], last_request.qs['limit'])
self.assertEqual(['created_at'], last_request.qs['sort_keys'])
self.assertEqual(['asc'], last_request.qs['sort_dirs'])
def test_get(self):
mock = self.mock_http_get(content=ACTION)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE_NAME % 'action',
json=ACTION)
action = self.actions.get('action')
@ -190,20 +194,17 @@ class TestActionsV2(base.BaseClientV2Test):
action.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'action')
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
url = self.TEST_URL + URL_TEMPLATE_NAME % 'action'
m = self.requests_mock.delete(url, status_code=204)
self.actions.delete('action')
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'action')
self.assertEqual(1, m.call_count)
def test_validate(self):
mock = self.mock_http_post(
status_code=200,
content={'valid': True}
)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json={'valid': True})
result = self.actions.validate(ACTION_DEF)
@ -211,17 +212,13 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertIn('valid', result)
self.assertTrue(result['valid'])
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(ACTION_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_with_file(self):
mock = self.mock_http_post(
status_code=200,
content={'valid': True}
)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json={'valid': True})
# The contents of action_v2.yaml must be identical to ACTION_DEF
path = pkg.resource_filename(
@ -235,19 +232,14 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertIn('valid', result)
self.assertTrue(result['valid'])
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(ACTION_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_failed(self):
mock_result = {
"valid": False,
"error": "mocked error message"
}
mock = self.mock_http_post(status_code=200, content=mock_result)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json={"valid": False,
"error": "mocked error message"})
result = self.actions.validate(INVALID_ACTION_DEF)
@ -257,14 +249,13 @@ class TestActionsV2(base.BaseClientV2Test):
self.assertIn('error', result)
self.assertIn("mocked error message", result['error'])
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
INVALID_ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_api_failed(self):
mock = self.mock_http_post(status_code=500, content={})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
status_code=500,
json={})
self.assertRaises(
api_base.APIException,
@ -272,8 +263,7 @@ class TestActionsV2(base.BaseClientV2Test):
ACTION_DEF
)
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
ACTION_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('text/plain', last_request.headers['content-type'])
self.assertEqual(ACTION_DEF, last_request.text)

@ -43,7 +43,9 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
def test_create(self):
data = copy.deepcopy(ENVIRONMENT)
mock = self.mock_http_post(content=data)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
status_code=201,
json=data)
env = self.environments.create(**data)
self.assertIsNotNone(env)
@ -51,7 +53,7 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
expected_data = copy.deepcopy(data)
expected_data['variables'] = json.dumps(expected_data['variables'])
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(expected_data))
self.assertEqual(expected_data, self.requests_mock.last_request.json())
def test_create_with_json_file_uri(self):
# The contents of env_v2.json must be equivalent to ENVIRONMENT
@ -68,7 +70,9 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
)
)
mock = self.mock_http_post(content=data)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
status_code=201,
json=data)
file_input = {'file': uri}
env = self.environments.create(**file_input)
@ -77,7 +81,7 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
expected_data = copy.deepcopy(data)
expected_data['variables'] = json.dumps(expected_data['variables'])
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(expected_data))
self.assertEqual(expected_data, self.requests_mock.last_request.json())
def test_create_without_name(self):
data = copy.deepcopy(ENVIRONMENT)
@ -92,7 +96,7 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
def test_update(self):
data = copy.deepcopy(ENVIRONMENT)
mock = self.mock_http_put(content=data)
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=data)
env = self.environments.update(**data)
self.assertIsNotNone(env)
@ -100,7 +104,7 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
expected_data = copy.deepcopy(data)
expected_data['variables'] = json.dumps(expected_data['variables'])
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(expected_data))
self.assertEqual(expected_data, self.requests_mock.last_request.json())
def test_update_with_yaml_file(self):
# The contents of env_v2.json must be equivalent to ENVIRONMENT
@ -113,8 +117,8 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
utils.get_contents_if_file(path)
)
)
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=data)
mock = self.mock_http_put(content=data)
file_input = {'file': path}
env = self.environments.update(**file_input)
@ -123,7 +127,7 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
expected_data = copy.deepcopy(data)
expected_data['variables'] = json.dumps(expected_data['variables'])
mock.assert_called_once_with(URL_TEMPLATE, json.dumps(expected_data))
self.assertEqual(expected_data, self.requests_mock.last_request.json())
def test_update_without_name(self):
data = copy.deepcopy(ENVIRONMENT)
@ -136,7 +140,8 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
self.assertEqual(400, e.error_code)
def test_list(self):
mock = self.mock_http_get(content={'environments': [ENVIRONMENT]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'environments': [ENVIRONMENT]})
environment_list = self.environments.list()
@ -149,10 +154,9 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
env.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_get(self):
mock = self.mock_http_get(content=ENVIRONMENT)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE_NAME % 'env',
json=ENVIRONMENT)
env = self.environments.get('env')
@ -162,11 +166,8 @@ class TestEnvironmentsV2(base.BaseClientV2Test):
env.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'env')
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
self.requests_mock.delete(self.TEST_URL + URL_TEMPLATE_NAME % 'env',
status_code=204)
self.environments.delete('env')
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'env')

@ -56,7 +56,10 @@ URL_TEMPLATE_ID = '/executions/%s'
class TestExecutionsV2(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content=EXEC)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=EXEC,
status_code=201)
body = {
'workflow_name': EXEC['workflow_name'],
'description': '',
@ -75,11 +78,13 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
self.assertEqual(URL_TEMPLATE, mock.call_args[0][0])
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_create_with_workflow_id(self):
mock = self.mock_http_post(content=EXEC)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=EXEC,
status_code=201)
body = {
'workflow_id': EXEC['workflow_id'],
'description': '',
@ -98,15 +103,17 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
self.assertEqual(URL_TEMPLATE, mock.call_args[0][0])
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_create_failure1(self):
self.mock_http_post(content=EXEC)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=EXEC,
status_code=201)
self.assertRaises(api_base.APIException, self.executions.create, '')
def test_update(self):
mock = self.mock_http_put(content=EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id']
self.requests_mock.put(url, json=EXEC)
body = {
'state': EXEC['state']
}
@ -120,11 +127,11 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
self.assertEqual(URL_TEMPLATE_ID % EXEC['id'], mock.call_args[0][0])
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_update_env(self):
mock = self.mock_http_put(content=EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id']
self.requests_mock.put(url, json=EXEC)
body = {
'state': EXEC['state'],
'params': {
@ -145,11 +152,11 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
self.assertEqual(URL_TEMPLATE_ID % EXEC['id'], mock.call_args[0][0])
self.assertDictEqual(body, json.loads(mock.call_args[0][1]))
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_list(self):
mock = self.mock_http_get(content={'executions': [EXEC, SUB_WF_EXEC]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'executions': [EXEC, SUB_WF_EXEC]})
execution_list = self.executions.list()
@ -165,12 +172,10 @@ class TestExecutionsV2(base.BaseClientV2Test):
execution_list[1].to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_list_with_pagination(self):
mock = self.mock_http_get(
content={'executions': [EXEC], 'next': '/executions?fake'}
)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'executions': [EXEC],
'next': '/executions?fake'})
execution_list = self.executions.list(
limit=1,
@ -180,13 +185,16 @@ class TestExecutionsV2(base.BaseClientV2Test):
self.assertEqual(1, len(execution_list))
last_request = self.requests_mock.last_request
# The url param order is unpredictable.
self.assertIn('limit=1', mock.call_args[0][0])
self.assertIn('sort_keys=created_at', mock.call_args[0][0])
self.assertIn('sort_dirs=asc', mock.call_args[0][0])
self.assertEqual(['1'], last_request.qs['limit'])
self.assertEqual(['created_at'], last_request.qs['sort_keys'])
self.assertEqual(['asc'], last_request.qs['sort_dirs'])
def test_get(self):
mock = self.mock_http_get(content=EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id']
self.requests_mock.get(url, json=EXEC)
ex = self.executions.get(EXEC['id'])
@ -195,10 +203,9 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_ID % EXEC['id'])
def test_get_sub_wf_ex(self):
mock = self.mock_http_get(content=SUB_WF_EXEC)
url = self.TEST_URL + URL_TEMPLATE_ID % SUB_WF_EXEC['id']
self.requests_mock.get(url, json=SUB_WF_EXEC)
ex = self.executions.get(SUB_WF_EXEC['id'])
@ -207,11 +214,8 @@ class TestExecutionsV2(base.BaseClientV2Test):
ex.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_ID % SUB_WF_EXEC['id'])
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id']
self.requests_mock.delete(url, status_code=204)
self.executions.delete(EXEC['id'])
mock.assert_called_once_with(URL_TEMPLATE_ID % EXEC['id'])

@ -13,7 +13,6 @@
# limitations under the License.
import copy
import json
from mistralclient.tests.unit.v2 import base
@ -34,7 +33,9 @@ WORKFLOW_MEMBER_URL = '/workflows/%s/members/%s' % (
class TestWorkflowMembers(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content=MEMBER)
self.requests_mock.post(self.TEST_URL + WORKFLOW_MEMBERS_URL,
json=MEMBER,
status_code=201)
mb = self.members.create(
MEMBER['resource_id'],
@ -44,16 +45,15 @@ class TestWorkflowMembers(base.BaseClientV2Test):
self.assertIsNotNone(mb)
mock.assert_called_once_with(
WORKFLOW_MEMBERS_URL,
json.dumps({'member_id': MEMBER['member_id']})
)
self.assertDictEqual({'member_id': MEMBER['member_id']},
self.requests_mock.last_request.json())
def test_update(self):
updated_member = copy.copy(MEMBER)
updated_member['status'] = 'accepted'
mock = self.mock_http_put(content=updated_member)
self.requests_mock.put(self.TEST_URL + WORKFLOW_MEMBER_URL,
json=updated_member)
mb = self.members.update(
MEMBER['resource_id'],
@ -63,22 +63,20 @@ class TestWorkflowMembers(base.BaseClientV2Test):
self.assertIsNotNone(mb)
mock.assert_called_once_with(
WORKFLOW_MEMBER_URL,
json.dumps({"status": "accepted"})
)
self.assertDictEqual({"status": "accepted"},
self.requests_mock.last_request.json())
def test_list(self):
mock = self.mock_http_get(content={'members': [MEMBER]})
self.requests_mock.get(self.TEST_URL + WORKFLOW_MEMBERS_URL,
json={'members': [MEMBER]})
mbs = self.members.list(MEMBER['resource_id'], MEMBER['resource_type'])
self.assertEqual(1, len(mbs))
mock.assert_called_once_with(WORKFLOW_MEMBERS_URL)
def test_get(self):
mock = self.mock_http_get(content=MEMBER)
self.requests_mock.get(self.TEST_URL + WORKFLOW_MEMBER_URL,
json=MEMBER)
mb = self.members.get(
MEMBER['resource_id'],
@ -88,15 +86,11 @@ class TestWorkflowMembers(base.BaseClientV2Test):
self.assertIsNotNone(mb)
mock.assert_called_once_with(WORKFLOW_MEMBER_URL)
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
self.requests_mock.delete(self.TEST_URL + WORKFLOW_MEMBER_URL,
status_code=204)
self.members.delete(
MEMBER['resource_id'],
MEMBER['resource_type'],
MEMBER['member_id']
)
mock.assert_called_once_with(WORKFLOW_MEMBER_URL)

@ -26,7 +26,8 @@ URL_TEMPLATE = '/services'
class TestServicesV2(base.BaseClientV2Test):
def test_list(self):
mock = self.mock_http_get(content={'services': [SERVICE]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'services': [SERVICE]})
service_list = self.services.list()
@ -38,5 +39,3 @@ class TestServicesV2(base.BaseClientV2Test):
services.Service(self.services, SERVICE).to_dict(),
srv.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)

@ -37,7 +37,8 @@ URL_TEMPLATE_ID = '/tasks/%s'
class TestTasksV2(base.BaseClientV2Test):
def test_list(self):
mock = self.mock_http_get(content={'tasks': [TASK]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'tasks': [TASK]})
task_list = self.tasks.list()
@ -48,10 +49,10 @@ class TestTasksV2(base.BaseClientV2Test):
tasks.Task(self.tasks, TASK).to_dict(),
task.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_get(self):
mock = self.mock_http_get(content=TASK)
url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id']
self.requests_mock.get(url, json=TASK)
task = self.tasks.get(TASK['id'])
@ -59,10 +60,10 @@ class TestTasksV2(base.BaseClientV2Test):
tasks.Task(self.tasks, TASK).to_dict(),
task.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_ID % TASK['id'])
def test_rerun(self):
mock = self.mock_http_put(content=TASK)
url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id']
self.requests_mock.put(url, json=TASK)
task = self.tasks.rerun(TASK['id'])
@ -71,19 +72,16 @@ class TestTasksV2(base.BaseClientV2Test):
task.to_dict()
)
self.assertEqual(1, mock.call_count)
self.assertEqual(URL_TEMPLATE_ID % TASK['id'], mock.call_args[0][0])
self.assertDictEqual(
{
'reset': True,
'state': 'RUNNING',
'id': TASK['id']
},
json.loads(mock.call_args[0][1])
)
body = {
'reset': True,
'state': 'RUNNING',
'id': TASK['id']
}
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_rerun_no_reset(self):
mock = self.mock_http_put(content=TASK)
url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id']
self.requests_mock.put(url, json=TASK)
task = self.tasks.rerun(TASK['id'], reset=False)
@ -92,19 +90,16 @@ class TestTasksV2(base.BaseClientV2Test):
task.to_dict()
)
self.assertEqual(1, mock.call_count)
self.assertEqual(URL_TEMPLATE_ID % TASK['id'], mock.call_args[0][0])
self.assertDictEqual(
{
'reset': False,
'state': 'RUNNING',
'id': TASK['id']
},
json.loads(mock.call_args[0][1])
)
body = {
'reset': False,
'state': 'RUNNING',
'id': TASK['id']
}
self.assertDictEqual(body, self.requests_mock.last_request.json())
def test_rerun_update_env(self):
mock = self.mock_http_put(content=TASK)
url = self.TEST_URL + URL_TEMPLATE_ID % TASK['id']
self.requests_mock.put(url, json=TASK)
task = self.tasks.rerun(TASK['id'], env={'k1': 'foobar'})
@ -113,14 +108,10 @@ class TestTasksV2(base.BaseClientV2Test):
task.to_dict()
)
self.assertEqual(1, mock.call_count)
self.assertEqual(URL_TEMPLATE_ID % TASK['id'], mock.call_args[0][0])
self.assertDictEqual(
{
'reset': True,
'state': 'RUNNING',
'id': TASK['id'],
'env': json.dumps({'k1': 'foobar'})
},
json.loads(mock.call_args[0][1])
)
body = {
'reset': True,
'state': 'RUNNING',
'id': TASK['id'],
'env': json.dumps({'k1': 'foobar'})
}
self.assertDictEqual(body, self.requests_mock.last_request.json())

@ -70,21 +70,24 @@ URL_TEMPLATE_VALIDATE = '/workbooks/validate'
class TestWorkbooksV2(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content=WORKBOOK)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=WORKBOOK,
status_code=201)
wb = self.workbooks.create(WB_DEF)
self.assertIsNotNone(wb)
self.assertEqual(WB_DEF, wb.definition)
mock.assert_called_once_with(
URL_TEMPLATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_create_with_file_uri(self):
mock = self.mock_http_post(content=WORKBOOK)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE,
json=WORKBOOK,
status_code=201)
# The contents of wb_v2.yaml must be identical to WB_DEF
path = pkg.resource_filename(
@ -100,28 +103,26 @@ class TestWorkbooksV2(base.BaseClientV2Test):
self.assertIsNotNone(wb)
self.assertEqual(WB_DEF, wb.definition)
mock.assert_called_once_with(
URL_TEMPLATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_update(self):
mock = self.mock_http_put(content=WORKBOOK)
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=WORKBOOK)
wb = self.workbooks.update(WB_DEF)
self.assertIsNotNone(wb)
self.assertEqual(WB_DEF, wb.definition)
mock.assert_called_once_with(
URL_TEMPLATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_update_with_file(self):
mock = self.mock_http_put(content=WORKBOOK)
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE, json=WORKBOOK)
# The contents of wb_v2.yaml must be identical to WB_DEF
path = pkg.resource_filename(
@ -134,14 +135,14 @@ class TestWorkbooksV2(base.BaseClientV2Test):
self.assertIsNotNone(wb)
self.assertEqual(WB_DEF, wb.definition)
mock.assert_called_once_with(
URL_TEMPLATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_list(self):
mock = self.mock_http_get(content={'workbooks': [WORKBOOK]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'workbooks': [WORKBOOK]})
workbook_list = self.workbooks.list()
@ -154,10 +155,9 @@ class TestWorkbooksV2(base.BaseClientV2Test):
wb.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_get(self):
mock = self.mock_http_get(content=WORKBOOK)
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wb'
self.requests_mock.get(url, json=WORKBOOK)
wb = self.workbooks.get('wb')
@ -167,20 +167,15 @@ class TestWorkbooksV2(base.BaseClientV2Test):
wb.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wb')
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wb'
self.requests_mock.delete(url, status_code=204)
self.workbooks.delete('wb')
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wb')
def test_validate(self):
mock = self.mock_http_post(
status_code=200,
content={'valid': True}
)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json={'valid': True})
result = self.workbooks.validate(WB_DEF)
@ -188,17 +183,14 @@ class TestWorkbooksV2(base.BaseClientV2Test):
self.assertIn('valid', result)
self.assertTrue(result['valid'])
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_with_file(self):
mock = self.mock_http_post(
status_code=200,
content={'valid': True}
)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json={'valid': True})
# The contents of wb_v2.yaml must be identical to WB_DEF
path = pkg.resource_filename(
@ -212,11 +204,10 @@ class TestWorkbooksV2(base.BaseClientV2Test):
self.assertIn('valid', result)
self.assertTrue(result['valid'])
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_failed(self):
mock_result = {
@ -225,7 +216,8 @@ class TestWorkbooksV2(base.BaseClientV2Test):
"can't be specified both"
}
mock = self.mock_http_post(status_code=200, content=mock_result)
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
json=mock_result)
result = self.workbooks.validate(INVALID_WB_DEF)
@ -238,14 +230,14 @@ class TestWorkbooksV2(base.BaseClientV2Test):
"can't be specified both", result['error']
)
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
INVALID_WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(INVALID_WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_validate_api_failed(self):
mock = self.mock_http_post(status_code=500, content={})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_VALIDATE,
status_code=500)
self.assertRaises(
api_base.APIException,
@ -253,8 +245,7 @@ class TestWorkbooksV2(base.BaseClientV2Test):
WB_DEF
)
mock.assert_called_once_with(
URL_TEMPLATE_VALIDATE,
WB_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WB_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])

@ -46,21 +46,24 @@ URL_TEMPLATE_NAME = '/workflows/%s'
class TestWorkflowsV2(base.BaseClientV2Test):
def test_create(self):
mock = self.mock_http_post(content={'workflows': [WORKFLOW]})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE,
json={'workflows': [WORKFLOW]},
status_code=201)
wfs = self.workflows.create(WF_DEF)
self.assertIsNotNone(wfs)
self.assertEqual(WF_DEF, wfs[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
WF_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WF_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_create_with_file(self):
mock = self.mock_http_post(content={'workflows': [WORKFLOW]})
self.requests_mock.post(self.TEST_URL + URL_TEMPLATE_SCOPE,
json={'workflows': [WORKFLOW]},
status_code=201)
# The contents of wf_v2.yaml must be identical to WF_DEF
path = pkg.resource_filename(
@ -73,42 +76,43 @@ class TestWorkflowsV2(base.BaseClientV2Test):
self.assertIsNotNone(wfs)
self.assertEqual(WF_DEF, wfs[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
WF_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WF_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_update(self):
mock = self.mock_http_put(content={'workflows': [WORKFLOW]})
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE,
json={'workflows': [WORKFLOW]})
wfs = self.workflows.update(WF_DEF)
self.assertIsNotNone(wfs)
self.assertEqual(WF_DEF, wfs[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
WF_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WF_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_update_with_id(self):
mock = self.mock_http_put(content=WORKFLOW)
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_NAME % '123',
json=WORKFLOW)
wf = self.workflows.update(WF_DEF, id='123')
self.assertIsNotNone(wf)
self.assertEqual(WF_DEF, wf.definition)
mock.assert_called_once_with(
'/workflows/123?scope=private',
WF_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual('scope=private', last_request.query)
self.assertEqual(WF_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_update_with_file_uri(self):
mock = self.mock_http_put(content={'workflows': [WORKFLOW]})
self.requests_mock.put(self.TEST_URL + URL_TEMPLATE_SCOPE,
json={'workflows': [WORKFLOW]})
# The contents of wf_v2.yaml must be identical to WF_DEF
path = pkg.resource_filename(
@ -124,14 +128,14 @@ class TestWorkflowsV2(base.BaseClientV2Test):
self.assertIsNotNone(wfs)
self.assertEqual(WF_DEF, wfs[0].definition)
mock.assert_called_once_with(
URL_TEMPLATE_SCOPE,
WF_DEF,
headers={'content-type': 'text/plain'}
)
last_request = self.requests_mock.last_request
self.assertEqual(WF_DEF, last_request.text)
self.assertEqual('text/plain', last_request.headers['content-type'])
def test_list(self):
mock = self.mock_http_get(content={'workflows': [WORKFLOW]})
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'workflows': [WORKFLOW]})
workflows_list = self.workflows.list()
@ -144,12 +148,10 @@ class TestWorkflowsV2(base.BaseClientV2Test):
wf.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE)
def test_list_with_pagination(self):
mock = self.mock_http_get(
content={'workflows': [WORKFLOW], 'next': '/workflows?fake'}
)
self.requests_mock.get(self.TEST_URL + URL_TEMPLATE,
json={'workflows': [WORKFLOW],
'next': '/workflows?fake'})
workflows_list = self.workflows.list(
limit=1,
@ -159,13 +161,16 @@ class TestWorkflowsV2(base.BaseClientV2Test):
self.assertEqual(1, len(workflows_list))
last_request = self.requests_mock.last_request
# The url param order is unpredictable.
self.assertIn('limit=1', mock.call_args[0][0])
self.assertIn('sort_keys=created_at', mock.call_args[0][0])
self.assertIn('sort_dirs=asc', mock.call_args[0][0])
self.assertEqual(['1'], last_request.qs['limit'])
self.assertEqual(['created_at'], last_request.qs['sort_keys'])
self.assertEqual(['asc'], last_request.qs['sort_dirs'])
def test_get(self):
mock = self.mock_http_get(content=WORKFLOW)
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf'
self.requests_mock.get(url, json=WORKFLOW)
wf = self.workflows.get('wf')
@ -175,11 +180,8 @@ class TestWorkflowsV2(base.BaseClientV2Test):
wf.to_dict()
)
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wf')
def test_delete(self):
mock = self.mock_http_delete(status_code=204)
url = self.TEST_URL + URL_TEMPLATE_NAME % 'wf'
self.requests_mock.delete(url, status_code=204)
self.workflows.delete('wf')
mock.assert_called_once_with(URL_TEMPLATE_NAME % 'wf')

@ -8,5 +8,6 @@ sphinx!=1.3b1,<1.3,>=1.2.1 # BSD
mock>=2.0 # BSD
nose # LGPL
oslotest>=1.10.0 # Apache-2.0
requests-mock>=1.0 # Apache-2.0
tempest>=12.1.0 # Apache-2.0
osprofiler>=1.4.0 # Apache-2.0