Mock a HTTP request that times out with HTTPretty
Asked Answered
B

1

12

Using the HTTPretty library for Python, I can create mock HTTP responses of choice and then pick them up i.e. with the requests library like so:

import httpretty
import requests

# set up a mock
httpretty.enable()
httpretty.register_uri(
            method=httpretty.GET,
            uri='http://www.fakeurl.com',
            status=200,
            body='My Response Body'
        )

response = requests.get('http://www.fakeurl.com')

# clean up
httpretty.disable()
httpretty.reset()

print(response)

Out: <Response [200]>

Is there also the possibility to register an uri which cannot be reached (e.g. connection timed out, connection refused, ...) such that no response is received at all (which is not the same as an established connection which gives an HTTP error code like 404)?

I want to use this behaviour in unit testing to ensure that my error handling works as expected (which does different things in case of 'no connection established' and 'connection established, bad bad HTTP status code'). As a workaround, I could try to connect to an invalid server like http://192.0.2.0 which would time out in any case. However, I would prefer to do all my unit testing without using any real network connections.

Brunabrunch answered 23/2, 2015 at 14:24 Comment(0)
B
11

Meanwhile I got it, using a HTTPretty callback body seems to produce the desired behaviour. See inline comments below. This is actually not exactly the same as I was looking for (it is not a server that cannot be reached and hence the request times out but a server that throws a timeout exception once it is reached, however, the effect is the same for my usecase.

Still, if anybody knows a different solution, I'm looking forward to it.

import httpretty
import requests

# enable HTTPretty
httpretty.enable()

# create a callback body that raises an exception when opened
def exceptionCallback(request, uri, headers):

    # raise your favourite exception here, e.g. requests.ConnectionError or requests.Timeout
    raise requests.Timeout('Connection timed out.')

# set up a mock and use the callback function as response's body
httpretty.register_uri(
            method=httpretty.GET,
            uri='http://www.fakeurl.com',
            status=200,
            body=exceptionCallback
        )

# try to get a response from the mock server and catch the exception
try:
    response = requests.get('http://www.fakeurl.com')
except requests.Timeout as e:

    print('requests.Timeout exception got caught...')
    print(e)

    # do whatever...

# clean up
httpretty.disable()
httpretty.reset()
Brunabrunch answered 24/2, 2015 at 9:41 Comment(1)
As you note, this does not really test the runtime behavior, because requests.get without the timeout parameter given hangs indefinitely even all these years later in requests 2.25.1. This can test what the code does if it times out, but does not test that it will timeout at all.Covariance

© 2022 - 2024 — McMap. All rights reserved.