Mitch Garnaat

Rewriting some tests and also rewriting the MockAWS module to automatically map …

…all responses in responses.py to mocks in the client.
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
13 13
14 import logging 14 import logging
15 15
16 -from botocore.exceptions import ClientError
17 -
18 import kappa.aws 16 import kappa.aws
19 17
20 LOG = logging.getLogger(__name__) 18 LOG = logging.getLogger(__name__)
......
1 +{
2 + "Statement":[
3 + {"Condition":
4 + {"ArnLike":{"AWS:SourceArn":"arn:aws:sns:us-east-1:123456789012:lambda_topic"}},
5 + "Resource":"arn:aws:lambda:us-east-1:123456789023:function:messageStore",
6 + "Action":"lambda:invokeFunction",
7 + "Principal":{"Service":"sns.amazonaws.com"},
8 + "Sid":"sns invoke","Effect":"Allow"
9 + }],
10 + "Id":"default",
11 + "Version":"2012-10-17"
12 +}
1 +import inspect
2 +
1 import mock 3 import mock
2 4
3 import tests.unit.responses as responses 5 import tests.unit.responses as responses
...@@ -6,40 +8,23 @@ import tests.unit.responses as responses ...@@ -6,40 +8,23 @@ import tests.unit.responses as responses
6 class MockAWS(object): 8 class MockAWS(object):
7 9
8 def __init__(self, profile=None, region=None): 10 def __init__(self, profile=None, region=None):
9 - pass 11 + self.response_map = {}
12 + for name, value in inspect.getmembers(responses):
13 + if name.startswith('__'):
14 + continue
15 + if '_' in name:
16 + service_name, request_name = name.split('_', 1)
17 + if service_name not in self.response_map:
18 + self.response_map[service_name] = {}
19 + self.response_map[service_name][request_name] = value
10 20
11 def create_client(self, client_name): 21 def create_client(self, client_name):
12 client = None 22 client = None
13 - if client_name == 'logs': 23 + if client_name in self.response_map:
14 - client = mock.Mock()
15 - choices = responses.logs_describe_log_groups
16 - client.describe_log_groups = mock.Mock(
17 - side_effect=choices)
18 - choices = responses.logs_describe_log_streams
19 - client.describe_log_streams = mock.Mock(
20 - side_effect=choices)
21 - choices = responses.logs_get_log_events
22 - client.get_log_events = mock.Mock(
23 - side_effect=choices)
24 - if client_name == 'cloudformation':
25 - client = mock.Mock()
26 - choices = responses.cfn_list_stack_resources
27 - client.list_stack_resources = mock.Mock(
28 - side_effect=choices)
29 - choices = responses.cfn_describe_stacks
30 - client.describe_stacks = mock.Mock(
31 - side_effect=choices)
32 - choices = responses.cfn_create_stack
33 - client.create_stack = mock.Mock(
34 - side_effect=choices)
35 - choices = responses.cfn_delete_stack
36 - client.delete_stack = mock.Mock(
37 - side_effect=choices)
38 - if client_name == 'iam':
39 client = mock.Mock() 24 client = mock.Mock()
40 - choices = responses.iam_get_role 25 + for request in self.response_map[client_name]:
41 - client.get_role = mock.Mock( 26 + response = self.response_map[client_name][request]
42 - side_effect=choices) 27 + setattr(client, request, mock.Mock(side_effect=response))
43 return client 28 return client
44 29
45 30
......
This diff is collapsed. Click to expand it.
1 +# Copyright (c) 2015 Mitch Garnaat http://garnaat.org/
2 +#
3 +# Licensed under the Apache License, Version 2.0 (the "License"). You
4 +# may not use this file except in compliance with the License. A copy of
5 +# the License is located at
6 +#
7 +# http://aws.amazon.com/apache2.0/
8 +#
9 +# or in the "license" file accompanying this file. This file is
10 +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11 +# ANY KIND, either express or implied. See the License for the specific
12 +# language governing permissions and limitations under the License.
13 +
14 +import unittest
15 +import os
16 +
17 +import mock
18 +
19 +from kappa.policy import Policy
20 +from tests.unit.mock_aws import get_aws
21 +
22 +Config1 = {
23 + 'name': 'FooPolicy',
24 + 'description': 'This is the Foo policy',
25 + 'document': 'FooPolicy.json'}
26 +
27 +Config2 = {
28 + 'name': 'BazPolicy',
29 + 'description': 'This is the Baz policy',
30 + 'document': 'BazPolicy.json'}
31 +
32 +
33 +def path(filename):
34 + return os.path.join(os.path.dirname(__file__), 'data', filename)
35 +
36 +
37 +class TestPolicy(unittest.TestCase):
38 +
39 + def setUp(self):
40 + self.aws_patch = mock.patch('kappa.aws.get_aws', get_aws)
41 + self.mock_aws = self.aws_patch.start()
42 + Config1['document'] = path(Config1['document'])
43 + Config2['document'] = path(Config2['document'])
44 +
45 + def tearDown(self):
46 + self.aws_patch.stop()
47 +
48 + def test_properties(self):
49 + mock_context = mock.Mock()
50 + policy = Policy(mock_context, Config1)
51 + self.assertEqual(policy.name, Config1['name'])
52 + self.assertEqual(policy.document, Config1['document'])
53 + self.assertEqual(policy.description, Config1['description'])
54 +
55 + def test_exists(self):
56 + mock_context = mock.Mock()
57 + policy = Policy(mock_context, Config1)
58 + self.assertTrue(policy.exists())
59 +
60 + def test_not_exists(self):
61 + mock_context = mock.Mock()
62 + policy = Policy(mock_context, Config2)
63 + self.assertFalse(policy.exists())
64 +
65 + def test_create(self):
66 + mock_context = mock.Mock()
67 + policy = Policy(mock_context, Config2)
68 + policy.create()
69 +
70 + def test_delete(self):
71 + mock_context = mock.Mock()
72 + policy = Policy(mock_context, Config1)
73 + policy.delete()
...@@ -12,56 +12,47 @@ ...@@ -12,56 +12,47 @@
12 # language governing permissions and limitations under the License. 12 # language governing permissions and limitations under the License.
13 13
14 import unittest 14 import unittest
15 -import os
16 15
17 import mock 16 import mock
18 17
19 -from kappa.stack import Stack 18 +from kappa.role import Role
20 from tests.unit.mock_aws import get_aws 19 from tests.unit.mock_aws import get_aws
21 20
22 -Config = { 21 +Config1 = {'name': 'FooRole'}
23 - 'template': 'roles.cf',
24 - 'stack_name': 'FooBar',
25 - 'exec_role': 'ExecRole',
26 - 'invoke_role': 'InvokeRole'}
27 22
23 +Config2 = {'name': 'BazRole'}
28 24
29 -def path(filename):
30 - return os.path.join(os.path.dirname(__file__), 'data', filename)
31 25
32 - 26 +class TestRole(unittest.TestCase):
33 -class TestStack(unittest.TestCase):
34 27
35 def setUp(self): 28 def setUp(self):
36 self.aws_patch = mock.patch('kappa.aws.get_aws', get_aws) 29 self.aws_patch = mock.patch('kappa.aws.get_aws', get_aws)
37 self.mock_aws = self.aws_patch.start() 30 self.mock_aws = self.aws_patch.start()
38 - Config['template'] = path(Config['template'])
39 31
40 def tearDown(self): 32 def tearDown(self):
41 self.aws_patch.stop() 33 self.aws_patch.stop()
42 34
43 def test_properties(self): 35 def test_properties(self):
44 mock_context = mock.Mock() 36 mock_context = mock.Mock()
45 - stack = Stack(mock_context, Config) 37 + role = Role(mock_context, Config1)
46 - self.assertEqual(stack.name, Config['stack_name']) 38 + self.assertEqual(role.name, Config1['name'])
47 - self.assertEqual(stack.template_path, Config['template'])
48 - self.assertEqual(stack.exec_role, Config['exec_role'])
49 - self.assertEqual(stack.invoke_role, Config['invoke_role'])
50 - self.assertEqual(
51 - stack.invoke_role_arn,
52 - 'arn:aws:iam::0123456789012:role/TestKinesis-InvokeRole-FOO')
53 39
54 def test_exists(self): 40 def test_exists(self):
55 mock_context = mock.Mock() 41 mock_context = mock.Mock()
56 - stack = Stack(mock_context, Config) 42 + role = Role(mock_context, Config1)
57 - self.assertTrue(stack.exists()) 43 + self.assertTrue(role.exists())
44 +
45 + def test_not_exists(self):
46 + mock_context = mock.Mock()
47 + role = Role(mock_context, Config2)
48 + self.assertFalse(role.exists())
58 49
59 - def test_update(self): 50 + def test_create(self):
60 mock_context = mock.Mock() 51 mock_context = mock.Mock()
61 - stack = Stack(mock_context, Config) 52 + role = Role(mock_context, Config2)
62 - stack.update() 53 + role.create()
63 54
64 def test_delete(self): 55 def test_delete(self):
65 mock_context = mock.Mock() 56 mock_context = mock.Mock()
66 - stack = Stack(mock_context, Config) 57 + role = Role(mock_context, Config1)
67 - stack.delete() 58 + role.delete()
......