How do I simulate connection errors and request timeouts in python unit tests

13,143

Untested code but...

def connection_error():
    raise requests.exceptions.ConnectionError

class TestSuitabilityFunctions(TestCase):
    @patch.object(module_that_youre_testing, "requests")
    def test_connection_error(self, mock_requests):
        mock_requests.get = MagicMock(side_effect=connection_error)
        with self.assertRaises(requests.exceptions.ConnectionError) as cm:
            resp = call_the_api()
        exception = cm.exception
        self.assertEqual(resp, {'request_error': 'ConnectionTimeout'})

... or similar should do the trick. Off the top of my head I can't remember how assertRaises interacts with errors that are caught. Maybe you don't even need the assertRaises part.

Share:
13,143

Related videos on Youtube

Tom
Author by

Tom

My name is Tom and I am a Computer Science major at Wentworth Institute of Technology. Find out more at http://tomleo.com

Updated on June 07, 2022

Comments

  • Tom
    Tom almost 2 years

    Suppose my django/flask application pulls in information from API's, how can I test that connection exceptions are caught and handled properly?

    So for example here is a function that calls an API:

    import requests
    def call_the_api():
        url = 'http://httpbin.org/get'
        try:
            req = requests.get(url)
            if req.json().get('errors'):
                logger.warn("API error response")
                return {'request_error': 'api_error_response'}
        except requests.exceptions.ConnectionError:
            logger.warn('ConnectionError')
            return {'request_error': 'ConnectionTimeout'}
        except requests.exception.Timeout:
            logger.warn('API request timed out')
            return {'request_error': 'Timeout'}
        except Exception, ex:
            logger.warn("API request Exception: %s", ex)
            return {'request_error': ex}
        else:
            return req.json()
    

    For testing responses from the API I found mock to be very useful.

    def mock_get_request():
        response = requests.get.return_value
        json_file = 'sample_response.json'
        json_file_path = os.path.join(os.path.dirname(__file__), json_file)
        with open(json_file_path, 'r') as f:
            response.content = response.text = f.read()
        response.status_code = 200
        response.encoding = 'utf-8'
        response.json = lambda: json.loads(response.content.decode(response.encoding))
        response.url = u'%s' % args[0]
        return response
    
    class TestSuitabilityFunctions(TestCase):
        def test_call_the_api(self):
            requests.get = MagicMock(side_effect=mock_get_request)
            resp = call_the_api()
            self.assertEqual(resp.get('url'), "http://httpbin.org/get")
    

    So my question is how would I go about simulating a connection timeout or error?

  • digitaldavenyc
    digitaldavenyc over 6 years
    This is a bad approach because it isn't properly mocking the request library, a decorator should be used so it doesn't mock requests outside of a single test.
  • Bheid
    Bheid almost 2 years
    @digitaldavenyc could you please provide the right way to do it?