HTTP server for testing environments
Project description
On-demand HTTP server for use in test environments where mocking underlying calls isn’t an option or where it’s necessary to have an actual HTTP server listening on a socket (e.g. testing IPv6 connectivity). Multiple HTTP servers can be run concurrently, and by default the port number is the next available unused port.
Compatibility
Spoof was tested with the following versions of Python (2.6.x and 3.3.x omitted due to SSL compatibility issues):
3.7.1
3.6.7
3.5.4
3.4.7
2.7.15
Installation
Install from source:
python setup.py install
Install from PyPI:
pip install spoof
Example usage
import unittest
import spoof
import thing
class TestThing(unittest.TestCase):
httpd = None
httpd6 = None
@classmethod
def setUpClass(cls):
# X509 certificates can be expensive to generate, so it should be done
# infrequently. Also, creating a new HTTP server instance with a new
# port number for each and every test can starve a system of available
# TCP/IP ports. Because of this, creating an `HTTPServer` instance
# should also be done infrequently, unless the port number is static.
sslContext = spoof.SSLContext.selfSigned()
cls.httpd = spoof.HTTPServer(sslContext=sslContext)
cls.httpd.start()
# IPv6-only, if needed; `HTTPServer` also accepts IPv6 addresses
cls.httpd6 = spoof.HTTPServer6(sslContext=sslContext)
cls.httpd6.start()
@classmethod
def tearDownClass(cls):
cls.httpd.stop()
cls.httpd6.stop()
cls.httpd = None
cls.httpd6 = None
def setUp(self):
# Calling `reset()` suffices to sanitize the HTTP server environment.
self.httpd.reset()
self.httpd.debug = False
self.thing = thing.Thing(self.httpd.address, self.httpd.port)
# or
self.altThing = thing.AltThing(self.httpd.url)
def tearDown(self):
self.thing = None
self.altThing = None
def test_thingUsingSpoof(self):
response1 = [200, [('Content-Type', 'application/json')], '{"id": 1111}']
response2 = [200, [('Content-Type', 'application/json')], '{"id": 2222}']
self.httpd.queueResponse(response1)
self.httpd.queueResponse(response2)
# HTTP debug logging, if needed
self.httpd.debug = True
self.thing.requiringTwoJSONresponses()
lastRequest = self.httpd.requests[-1]
expectedContent = '{"action": "rename", "old": 1111, "new": 2222}'
self.assertEqual(expectedContent, lastRequest.content)
Squelching SSL warnings
Some libraries like Requests will complain loudly or refuse to connect to HTTP servers with a self-signed SSL certificate. The preferred way to handle this is to use the verify property in requests.Session to trust the certificate:
import requests
import spoof
cert, key = spoof.SSLContext.createSelfSignedCert()
sslContext = spoof.SSLContext.fromCertChain(cert, key)
httpd = spoof.HTTPServer(sslContext=sslContext)
httpd.queueResponse((200, (), 'OK'))
httpd.start()
# trust self-signed certificate
session = requests.Session()
session.verify = cert
response = session.get(httpd.url + '/uri/path')
print(response.status_code, response.content)
httpd.stop()
If verifying the certificate is not an option, another way to work around this is to monkeypatch the requests library in the testing code. For example:
import requests
certVerify = requests.adapters.HTTPAdapter.cert_verify
def certNoVerify(self, conn, url, verify, cert):
return certVerify(self, conn, url, False, cert)
requests.adapters.HTTPAdapter.cert_verify = certNoVerify
requests.packages.urllib3.disable_warnings()
Another common case is libraries that leverage ssl directly. One way to work around this is to globally set the default context to unverified. For example:
import ssl
try:
createUnverifiedHttpsContext = ssl._create_unverified_context
except AttributeError:
# ignore if ssl context not verified by default
pass
else:
ssl._create_default_https_context = createUnverifiedHttpsContext
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for spoof-1.3.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e66e34a52dc99c47fae42879db64b7f679c66badf20b71fa56d9cee9aa656584 |
|
MD5 | ccb002e5c8535ccd207b9f7a502d718f |
|
BLAKE2b-256 | 5b156b64e75b0481e694cbfa7de5980fb905fd8be1a10fe5a771d0308a0daa1d |