@@ -366,3 +366,92 @@ In the above code, all the request.get() calls could be in a different thread,
366366eg. running in parallel, but the exit condition of the context object is to wait
367367for the specified conditions.
368368
369+
370+ Emulating connection refused error
371+ ----------------------------------
372+
373+ If by any chance, you want to emulate network errors such as *Connection reset
374+ by peer * or *Connection refused *, you can simply do it by connecting to a random
375+ port number where no service is listening:
376+
377+ .. code-block :: python
378+
379+ import pytest
380+ import requests
381+
382+ def test_connection_refused ():
383+ # assumes that there's no server listening at localhost:1234
384+ with pytest.raises(requests.exceptions.ConnectionError):
385+ requests.get(" http://localhost:1234" )
386+
387+
388+ However connecting to the port where the httpserver had been started will still
389+ succeed as the server is running continuously. This is working by design as
390+ starting/stopping the server is costly.
391+
392+ .. code-block :: python
393+
394+ import pytest
395+ import requests
396+
397+ # setting a fixed port for httpserver
398+ @pytest.fixture
399+ def httpserver_listen_address ():
400+ return (" 127.0.0.1" , 8000 )
401+
402+ # this test will pass
403+ def test_normal_connection (httpserver ):
404+ httpserver.expect_request(" /foo" ).respond_with_data(" foo" )
405+ assert requests.get(" http://localhost:8000/foo" ).text == " foo"
406+
407+
408+ # this tess will FAIL, as httpserver started in test_normal_connection is
409+ # still running
410+ def test_connection_refused ():
411+ with pytest.raises(requests.exceptions.ConnectionError):
412+ # this won't get Connection refused error as the server is still
413+ # running.
414+ # it will get HTTP status 500 as the handlers registered in
415+ # test_normal_connection have been removed
416+ requests.get(" http://localhost:8000/foo" )
417+
418+
419+
420+ To solve the issue, the httpserver can be stopped explicitly. It will start
421+ implicitly when the first test starts to use it. So the
422+ ``test_connection_refused `` test can be re-written to this:
423+
424+ .. code-block :: python
425+
426+ def test_connection_refused (httpserver ):
427+ httpserver.stop() # stop the server explicitly
428+ with pytest.raises(requests.exceptions.ConnectionError):
429+ requests.get(" http://localhost:8000/foo" )
430+
431+
432+ Emulating timeout
433+ -----------------
434+
435+ To emulate timeout, there's one way to register a handler function which will sleep for a
436+ given amount of time.
437+
438+ .. code-block :: python
439+
440+ import time
441+ from pytest_httpserver import HTTPServer
442+ import pytest
443+ import requests
444+
445+
446+ def sleeping (request ):
447+ time.sleep(2 ) # this should be greater than the client's timeout parameter
448+
449+
450+ def test_timeout (httpserver : HTTPServer):
451+ httpserver.expect_request(" /baz" ).respond_with_handler(sleeping)
452+ with pytest.raises(requests.exceptions.ReadTimeout):
453+ assert requests.get(httpserver.url_for(" /baz" ), timeout = 1 )
454+
455+
456+ There's one drawback though: the test takes 2 seconds to run as it waits the
457+ handler thread to be completed.
0 commit comments