forked from linode/linode_api4-python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbase.py
More file actions
185 lines (143 loc) · 5.1 KB
/
Copy pathbase.py
File metadata and controls
185 lines (143 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
from unittest import TestCase
from mock import patch
import json
from linode import LinodeClient
from .fixtures import TestFixtures
FIXTURES = TestFixtures()
class MockResponse:
def __init__(self, status_code, json, headers={}):
self.status_code = status_code
self._json = json
# Headers is a dict, do not want to use a getter here
self.headers = headers
def json(self):
return self._json
def load_json(url):
"""
Returns a dict from a .json file living in /test/response/GET/{url}.json
:param url: The URL being accessed whose JSON is to be returned
:returns: A dict containing the loaded JSON from that file
"""
formatted_url = url
while formatted_url.startswith('/'):
formatted_url = formatted_url[1:]
return FIXTURES.get_fixture(formatted_url)
def mock_get(url, headers=None, data=None):
"""
Loads the response from a JSON file
"""
response = load_json(url)
return MockResponse(200, response)
class MethodMock:
"""
This class is used to mock methods on requests and store the parameters
and headers it was called with.
"""
def __init__(self, method, return_dct):
"""
Creates and initiates a new MethodMock with the given details
:param method: The HTTP method we are mocking
:param return_dct: The python dct to returned, or the URL for a JSON
file to return
"""
self.method = method
if isinstance(return_dct, dict):
self.return_dct = return_dct
elif isinstance(return_dct, str):
self.return_dct = load_json(return_dct)
else:
raise TypeError('return_dct must be a dict or a URL from which the '
'JSON could be loaded')
def __enter__(self):
"""
Begins the method mocking
"""
self.patch = patch(
'linode.linode_client.requests.'+self.method,
return_value=MockResponse(200, self.return_dct)
)
self.mock = self.patch.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
"""
Removed the mocked method
"""
self.patch.stop()
@property
def call_args(self):
"""
A shortcut to accessing the underlying mock object's call args
"""
return self.mock.call_args
@property
def call_data_raw(self):
"""
A shortcut to access the raw call data, not parsed as JSON
"""
return self.mock.call_args[1]['data']
@property
def call_url(self):
"""
A shortcut to accessing the URL called on the underlying mock. We
chop off the first character because our testing base_url has a leading
/ we don't want to see.
"""
return self.mock.call_args[0][0][1:]
@property
def call_data(self):
"""
A shortcut to getting the data param this was called with. Removes all
keys whose values are None
"""
data = json.loads(self.mock.call_args[1]['data'])
return { k: v for k, v in data.items() if v is not None }
@property
def call_headers(self):
"""
A shortcut to getting the headers param this was called with
"""
return self.mock.call_args[1]['headers']
class ClientBaseCase(TestCase):
def setUp(self):
self.client = LinodeClient('testing', base_url='/')
self.get_patch = patch('linode.linode_client.requests.get',
side_effect=mock_get)
self.get_patch.start()
def tearDown(self):
self.get_patch.stop()
def mock_get(self, return_dct):
"""
Returns a MethodMock mocking a GET. This should be used in a with
statement.
:param return_dct: The JSON that should be returned from this GET
:returns: A MethodMock object who will capture the parameters of the
mocked requests
"""
return MethodMock('get', return_dct)
def mock_post(self, return_dct):
"""
Returns a MethodMock mocking a POST. This should be used in a with
statement.
:param return_dct: The JSON that should be returned from this POST
:returns: A MethodMock object who will capture the parameters of the
mocked requests
"""
return MethodMock('post', return_dct)
def mock_put(self, return_dct):
"""
Returns a MethodMock mocking a PUT. This should be used in a with
statement.
:param return_dct: The JSON that should be returned from this PUT
:returns: A MethodMock object who will capture the parameters of the
mocked requests
"""
return MethodMock('put', return_dct)
def mock_delete(self):
"""
Returns a MethodMock mocking a DELETE. This should be used in a with
statement.
:param return_dct: The JSON that should be returned from this DELETE
:returns: A MethodMock object who will capture the parameters of the
mocked requests
"""
return MethodMock('delete', {})