class HttpServiceTests(PatchedSessionTests): def setUp(self): PatchedSessionTests.setUp(self) self.service = HTTPServiceClient('http://service.com/') def test_returning_responses_from_all_session_calls(self): self.assertEqual(self.service.get('/path'), self.response) self.assertEqual(self.service.put('/path'), self.response) self.assertEqual(self.service.delete('/path'), self.response) self.assertEqual(self.service.post('/path'), self.response) self.assertEqual(self.service.patch('/path'), self.response) self.assertEqual(self.service.options('/path'), self.response) self.assertEqual(self.service.head('/path'), self.response) def test_get_request_with_params(self): """GET request with url parameters""" self.service.get('/get-endpoint', params={'foo': 'bar'}) self.request.assert_called_with( method='GET', url='http://service.com/get-endpoint', allow_redirects=True, params={'foo': 'bar'}) def test_minimal_post_request(self): """minimal POST request""" self.service.post('/post-endpoint') self.request.assert_called_with( method='POST', url='http://service.com/post-endpoint', json=None, data=None) def test_minimal_put_request(self): """minimal PUT request""" self.service.put('/put-endpoint') self.request.assert_called_with( method='PUT', url='http://service.com/put-endpoint', data=None) def test_minimal_delete_request(self): """minimal DELETE request""" self.service.delete('/delete-endpoint') self.request.assert_called_with( method='DELETE', url='http://service.com/delete-endpoint') def test_unacceptable_response(self): def get(): self.service.get('/get-endpoint') acceptable = True self.service.is_acceptable = lambda *args: acceptable get() acceptable = False self.assertRaises(HTTPServiceError, get) def test_headers_are_passed_and_overridable(self): service = HTTPServiceClient( url='http://localhost/', headers={ 'name': 'value', 'thomas': 'kittens'}) service.get('/') self.request.assert_called_with( headers={'thomas': 'kittens', 'name': 'value'}, method='GET', url='http://localhost/', allow_redirects=True) service.get('/', headers={'thomas': 'homegirl'}) self.request.assert_called_with( headers={'thomas': 'homegirl', 'name': 'value'}, method='GET', url='http://localhost/', allow_redirects=True) def test_sets_authentication_when_provided(self): service = HTTPServiceClient( url='http://localhost/', auth=('foo', 'bar'), ) service.get('/authed-endpoint') self.request.assert_called_with( method='GET', url='http://localhost/authed-endpoint', allow_redirects=True, auth=('foo', 'bar')) @patch('demands.log') def test_logs_authentication_when_provided(self, mock_log): service = HTTPServiceClient( url='http://localhost/', auth=('foo', 'bar'), ) service.get('/authed-endpoint') debug_msgs = get_parsed_log_messages(mock_log, 'debug') self.assertIn('Authentication', debug_msgs[2]) def test_client_identification_adds_user_agent_header(self): """client identification adds User-Agent header""" service = HTTPServiceClient( url='http://localhost/', client_name='my_client', client_version='1.2.3', app_name='my_app', headers={'Foo': 'Bar'}, ) service.get('/test') self.request.assert_called_with( method='GET', url='http://localhost/test', allow_redirects=True, headers={'User-Agent': 'my_client 1.2.3 - my_app', 'Foo': 'Bar'}) def test_post_send_raise_exception_in_case_of_error(self): self.response.configure_mock(url='http://broken/', status_code=500) with self.assertRaises(HTTPServiceError): self.service.request('METHOD', 'http://broken/') def test_post_send_raises_exception_with_details_on_error(self): self.response.configure_mock( status_code=500, content='content', url='http://broken/') with self.assertRaises(HTTPServiceError) as e: self.service.request('METHOD', 'http://broken/') self.assertEqual(e.exception.code, 500) self.assertEqual(e.exception.details, 'content') self.assertTrue(e.message.startswith( 'Unexpected response: url: ' 'http://broken/, code: 500, details: ' )) def test_post_sends_no_exception_in_case_of_expected_response_code(self): self.response.configure_mock( status_code=404, content='content', url='http://notfound/') self.service.request( 'METHOD', 'http://notfound/', expected_response_codes=(404,)) def test_santization_of_request_parameters_removes_unknowns(self): lots_of_params = { 'expected_response_codes': (404,), 'method': 'METHOD', 'something_odd': True } self.assertEqual( self.service._sanitize_request_params(lots_of_params), {'method': 'METHOD'}) def test_santization_of_verify_parameters(self): lots_of_params = { 'expected_response_codes': (404,), 'method': 'METHOD', 'verify_ssl': '/some/path', } self.assertEqual( self.service._sanitize_request_params(lots_of_params), {'method': 'METHOD', 'verify': '/some/path'}) def test_url_is_composed_properly(self): service = HTTPServiceClient('http://service.com/some/path/') service.get('/get-endpoint') self.request.assert_called_with( method='GET', url='http://service.com/some/path/get-endpoint', allow_redirects=True ) def test_url_is_composed_properly_if_path_is_empty(self): service = HTTPServiceClient( 'http://service.com/some/path/get-endpoint') service.get('') self.request.assert_called_with( method='GET', url='http://service.com/some/path/get-endpoint', allow_redirects=True ) def test_pre_send_sets_max_retries(self): self.service.pre_send({'max_retries': 2}) for adapter in itervalues(self.service.adapters): self.assertEqual(adapter.max_retries, 2) def test_pre_send_defaults_max_retries_to_zero(self): self.service.pre_send({'max_retries': 2}) self.service.pre_send({}) for adapter in itervalues(self.service.adapters): self.assertEqual(adapter.max_retries, 0)