Search code examples
pythonmultithreadingunit-testinghttpretty

How can I get httpretty to stop printing exceptions during testing?


I have a test which simulates a request from a remote server which does not exist:

    @httpretty.activate
    def test_no_such_host(self):

        def no_such_host(request, uri, headers):
            raise requests.ConnectionError()

        httpretty.register_uri(
                'GET',
                EXAMPLE_WEBFINGER_URL,
                status=200,
                headers = {
                    'Content-Type': 'application/jrd+json',
                    },
                body = no_such_host,
                )

        webfinger = get_webfinger(
                EXAMPLE_USERNAME,
                EXAMPLE_HOSTNAME,
                )

        self.assertEqual(
                webfinger.url,
                None,
                )

get_webfinger does in fact catch ConnectionError. When it runs, the test passes-- but it also reports the ConnectionError exception as coming from an httpretty thread:

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/home/marnanel/alpha/lib/python3.6/site-packages/httpretty/core.py", line 781, in fill_filekind
    status, headers, self.body = self.callable_body(self.request, self.info.full_url(), headers)
  File "/home/marnanel/proj/kepi/kepi/sombrero_sendpub/tests/test_webfinger.py", line 183, in no_such_host
    raise requests.ConnectionError()
requests.exceptions.ConnectionError

.
----------------------------------------------------------------------
Ran 1 test in 0.117s

OK
Destroying test database for alias 'default'...

There is no threading in the unit test or in the code being tested. This is one of many similar tests. The ones which don't involve exceptions all run perfectly.

How can I get it to stop printing the exception?


Solution

  • HTTPretty uses a thread to simulate socket timeouts but are not handling exceptions correctly, see issue #334. The latter proposes a method for handling exceptions, but that hasn't been picked up by the maintainers (yet).

    However, the message you see is printed by the default threading.excepthook() implementation. You can set your own hook; a no-op lambda would silence the errors:

    threading.excepthook = lambda a: None
    

    You could use a context manager to disable the hook temporarily:

    import threading
    from contextlib import contextmanager
    
    @contextmanager
    def suppress_thread_exceptions():
        orig = threading.excepthook
        threading.excepthook = lambda a: None
        try:
            yield
        finally:
            threading.excepthook = orig
    

    then use the above in your tests:

    with suppress_thread_exceptions():
        # use HTTPretty