Reputation: 2052
I'd like to make sure my unit tests do not try to connect to Internet, is there a way to raise an exception when they do?
There was a similar question Python: block network connections for testing purposes?, but the solution proposed there blocks all socket connections, including the database ones, which is not acceptable for Django tests.
Upvotes: 4
Views: 2350
Reputation: 6189
httpretty
solves this problem.
Write a custom test runner where you disable only 3rd party API calls, only in your test suite.
# common/test_runner.py
import httpretty
from django.test.runner import DiscoverRunner
class CustomTestRunner(DiscoverRunner):
def run_tests(self, *args, **kwargs):
with httpretty.enabled(allow_net_connect=False):
return super().run_tests(*args, **kwargs)
add this new test runner to your settings
TEST_RUNNER = "common.test_runner.CustomTestRunner"
And from now on all external API calls have to be mocked or httpretty.errors.UnmockedError
will be raised.
Alternatively, if your project uses responses
library, responses.activate
or responses.start
should work similarly.
Upvotes: 2
Reputation: 2052
Found out a way to do this. You can paste this into your settings.
if 'test' in sys.argv:
# Block Internet access during tests
import urllib2
import httplib
import httplib2
def _raise_http_error(*args, **kwargs):
raise urllib2.URLError("I told you not to use the Internet!")
class AngryHandler(urllib2.BaseHandler):
handler_order = 1
def default_open(self, req):
_raise_http_error()
opener = urllib2.build_opener(AngryHandler)
urllib2.install_opener(opener)
_HTTPHandler = urllib2.HTTPHandler
urllib2.HTTPHandler = AngryHandler
httplib.HTTPConnection.connect = lambda self: None
httplib.HTTPSConnection.connect = lambda self: None
httplib.HTTPConnection.request = _raise_http_error
httplib.HTTPSConnection.request = _raise_http_error
httplib2.Http.request = _raise_http_error
Upvotes: 5
Reputation: 2189
Take a look at vcrpy: https://github.com/kevin1024/vcrpy
The first time you run the test it'll make the external request. Every time after that it'll use a fixture that it stored from the first call. The external requests never get made again, which is what you're trying to accomplish.
Usage is dead simple using a decorator on your unit test:
@vcr.use_cassette('fixtures/vcr_cassettes/synopsis.yaml')
def test_iana():
response = urllib2.urlopen('http://www.iana.org/domains/reserved').read()
assert 'Example domains' in response
Supports any request made using the following libraries:
Upvotes: 2