How can I use unittest.mock to remove side effects from code?
<p>I have a function with several points of failure:</p>

<pre><code>def setup_foo(creds):
    """
    Creates a foo instance with which we can leverage the Foo virtualization
    platform.

    :param creds: A dictionary containing the authorization url, username,
                  password, and version associated with the Foo
                  cluster.
    :type creds:  dict
    """

    try:
        foo = Foo(version=creds['VERSION'],
                  username=creds['USERNAME'],
                  password=creds['PASSWORD'],
                  auth_url=creds['AUTH_URL'])

        foo.authenticate()
        return foo
    except (OSError, NotFound, ClientException) as e:
        raise UnreachableEndpoint("Couldn't find auth_url {0}".format(creds['AUTH_URL']))
    except Unauthorized as e:
        raise UnauthorizedUser("Wrong username or password.")
    except UnsupportedVersion as e:
        raise Unsupported("We only support Foo API with major version 2")
</code></pre>

<p>and I'd like to test that all the relevant exceptions are caught (albeit not handled well currently).</p>

<p>I have an initial test case that passes:</p>

<pre><code>def test_setup_foo_failing_auth_url_endpoint_does_not_exist(self):
    dummy_creds = {
        'AUTH_URL' : 'http://bogus.example.com/v2.0',
        'USERNAME' : '', #intentionally blank.
        'PASSWORD' : '', #intentionally blank.
        'VERSION'  : 2 
    }
    with self.assertRaises(UnreachableEndpoint):
        foo = osu.setup_foo(dummy_creds)
</code></pre>

<p>but how can I make my test framework believe that the AUTH_URL is actually a valid/reachable URL?</p>

<p>I've created a mock class for <code>Foo</code>:</p>

<pre><code>class MockFoo(Foo):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
</code></pre>

<p>and my thought is mock the call to <code>setup_foo</code> and remove the side effect of raising an <code>UnreachableEndpoint</code> exception. I know how to <em>add</em> side-effects to a <code>Mock</code> with <code>unittest.mock</code>, but how can I remove them?</p>

<p>If you wish to mock out http servers from bogus urls, I suggest you check out <a href="https://github.com/gabrielfalcao/HTTPretty" rel="nofollow">HTTPretty</a>. It mocks out urls at a socket level so it can trick most Python HTTP libraries that it's a valid url.</p>

<p>I suggest the following setup for your unittest:</p>

<pre><code>class FooTest(unittest.TestCase):
    def setUp(self):
        httpretty.register_uri(httpretty.GET, "http://bogus.example.com/v2.0",
                       body='[{"response": "Valid"}]',
                       content_type="application/json")
    @httpretty.activate
    def test_test_case(self):
        resp = requests.get("http://bogus.example.com/v2.0")
        self.assertEquals(resp.status_code, 200)
</code></pre>

<p>Note that the mock will only apply to stacks that are decorated with <code>http.activate</code> decorator, so it won't leak to other places in your code that you don't want to mock. Hope that makes sense.</p>

python unit-testing python-3.x exception-handling python-unittest.mock