Skip to content
Advertisement

How to unit test a function that creates a connection object assuming there will not be internet access?

I have a python function that creates a Client object from the aiosnow module, which is an API wrapper for ServiceNow like this:

from aiosnow import Client


def create_snow_client(url: str, user_name: str, pwd: str) -> Client:
    """Creates ServiceNow client object for interacting with the API."""

    client = Client(
        url,
        basic_auth=(user_name, pwd),
    )

    return client

Assuming I will not have internet connection during unit testing, how or what part am I supposed to make the unit test for, which part am I supposed to mock?

Advertisement

Answer

One approach is just to guarantee that the Client constructor has been called. You can accomplish this with unittest.mock.Mock().assert_called (or some variant of it, like assert_called_with). This will entail mocking the Client class, so that when the test runs and you call the Client constructor, no code from Client actually runs. The mock gets called and then you can make assertions based on what you expected to happen.

This is a correct approach because you and your test don’t care about the inner workings of the Client class. You’re testing your function which is supposed to create a client, not that Client works correctly. By mocking out the Client class, your test simply guarantees that your code instantiated a Client, but doesn’t run any Client code.

Here’s an example:

from unittest.mock import patch


class Foo():
    def __init__(self):
        print("New Foo!")


def use_foo():
    print(f"foo: {Foo()}")


@patch("__main__.Foo")
def test_foo(mocked_foo):
    use_foo()
    print(f"Mocked Foo called? {mocked_foo.called}")


def main():
    print("Using foon")
    use_foo()

    print("nTesting foon")
    test_foo()


if __name__ == "__main__":
    main()

and here’s the corresponding output:

Using foo

New Foo!
foo: <__main__.Foo object at 0x7fdfcaba2ac0>

Testing foo

foo: <MagicMock name='Foo()' id='140599155357056'>
Mocked Foo called? True

You can see that "New Foo" did not appear in the output of the test, because the class has been mocked.

You can read more about mocking in the Python docs.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement