From 5fb46952c6df813ca136950e72c49594a6ebd0e4 Mon Sep 17 00:00:00 2001 From: medmunds Date: Wed, 17 Jan 2018 13:53:06 -0800 Subject: [PATCH] Tests: fix MockRequestsBackend.get_api_call_arg edge cases get_api_call_arg had incorrectly returned None if a kwarg was passed to the mocked function with a False-y value (e.g., [] or {}) get_api_call_json had only considered data param, ignoring json param requests added a while back --- tests/mock_requests_backend.py | 61 ++++++++++++++++++------------- tests/test_mailgun_backend.py | 2 +- tests/test_sendgrid_v2_backend.py | 2 +- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/tests/mock_requests_backend.py b/tests/mock_requests_backend.py index 2409ee7..c6cbe30 100644 --- a/tests/mock_requests_backend.py +++ b/tests/mock_requests_backend.py @@ -51,20 +51,16 @@ class RequestsBackendMockAPITestCase(SimpleTestCase, AnymailTestMixin): # This assumes the last (or only) call to requests.Session.request is the API call of interest. if self.mock_request.call_args is None: raise AssertionError("No ESP API was called") - (args, kwargs) = self.mock_request.call_args - try: - actual_method = kwargs.get('method', None) or args[1] - actual_url = kwargs.get('url', None) or args[2] - except IndexError: - raise AssertionError("API was called without a method or url (?!)") - if actual_method != method: - raise AssertionError("API was not called using %s. (%s was used instead.)" - % (method, actual_method)) - if not actual_url.endswith(url): - raise AssertionError("API was not called at %s\n(It was called at %s)" - % (url, actual_url)) + if method is not None: + actual_method = self.get_api_call_arg('method') + if actual_method != method: + self.fail("API was not called using %s. (%s was used instead.)" % (method, actual_method)) + if url is not None: + actual_url = self.get_api_call_arg('url') + if not actual_url.endswith(url): + self.fail("API was not called at %s\n(It was called at %s)" % (url, actual_url)) - def get_api_call_arg(self, kwarg, pos, required=True): + def get_api_call_arg(self, kwarg, required=True): """Returns an argument passed to the mock ESP API. Fails test if API wasn't called. @@ -73,36 +69,51 @@ class RequestsBackendMockAPITestCase(SimpleTestCase, AnymailTestMixin): raise AssertionError("API was not called") (args, kwargs) = self.mock_request.call_args try: - return kwargs.get(kwarg, None) or args[pos] - except IndexError: - if required: - raise AssertionError("API was called without required %s" % kwarg) - else: - return None + return kwargs[kwarg] + except KeyError: + pass + + try: + # positional arg? This is the order of requests.Session.request params: + pos = ('method', 'url', 'params', 'data', 'headers', 'cookies', 'files', 'auth', + 'timeout', 'allow_redirects', 'proxies', 'hooks', 'stream', 'verify', 'cert', 'json', + ).index(kwarg) + return args[pos] + except (ValueError, IndexError): + pass + + if required: + self.fail("API was called without required arg '%s'" % kwarg) + return None def get_api_call_params(self, required=True): """Returns the query params sent to the mock ESP API.""" - return self.get_api_call_arg('params', 3, required) + return self.get_api_call_arg('params', required) def get_api_call_data(self, required=True): """Returns the raw data sent to the mock ESP API.""" - return self.get_api_call_arg('data', 4, required) + return self.get_api_call_arg('data', required) def get_api_call_json(self, required=True): """Returns the data sent to the mock ESP API, json-parsed""" - return json.loads(self.get_api_call_data(required)) + # could be either the data param (as json str) or the json param (needing formatting) + value = self.get_api_call_arg('data', required=False) + if value is not None: + return json.loads(value) + else: + return self.get_api_call_arg('json', required) def get_api_call_headers(self, required=True): """Returns the headers sent to the mock ESP API""" - return self.get_api_call_arg('headers', 5, required) + return self.get_api_call_arg('headers', required) def get_api_call_files(self, required=True): """Returns the files sent to the mock ESP API""" - return self.get_api_call_arg('files', 7, required) + return self.get_api_call_arg('files', required) def get_api_call_auth(self, required=True): """Returns the auth sent to the mock ESP API""" - return self.get_api_call_arg('auth', 8, required) + return self.get_api_call_arg('auth', required) def assert_esp_not_called(self, msg=None): if self.mock_request.called: diff --git a/tests/test_mailgun_backend.py b/tests/test_mailgun_backend.py index 07997aa..c53bb7b 100644 --- a/tests/test_mailgun_backend.py +++ b/tests/test_mailgun_backend.py @@ -108,7 +108,7 @@ class MailgunBackendStandardEmailTests(MailgunBackendMockAPITestCase): self.assertEqual(data['html'], html_content) # Don't accidentally send the html part as an attachment: files = self.get_api_call_files(required=False) - self.assertIsNone(files) + self.assertFalse(files) def test_html_only_message(self): html_content = '

This is an important message.

' diff --git a/tests/test_sendgrid_v2_backend.py b/tests/test_sendgrid_v2_backend.py index 9eca867..617fde0 100644 --- a/tests/test_sendgrid_v2_backend.py +++ b/tests/test_sendgrid_v2_backend.py @@ -146,7 +146,7 @@ class SendGridBackendStandardEmailTests(SendGridBackendMockAPITestCase): self.assertEqual(data['html'], html_content) # Don't accidentally send the html part as an attachment: files = self.get_api_call_files(required=False) - self.assertIsNone(files) + self.assertFalse(files) def test_html_only_message(self): html_content = '

This is an important message.

'