a11smiles
a11smiles

Reputation: 1258

Patch attribute of mocked class

I'm attempting to mock a class.

The class I'm attempting to mock looks like the following (lines have been removed for brevity):

class Connection(object):
    """Connection.
    """

    def __init__(self, base_url=None, creds=None, user_agent=None):
        self.clients = ClientFactory(self)

As you can see, it has a property called clients.

My method under test:

    def _auth(self, credentials):
        connection = Connection(base_url=f'https://someurl.com', creds=credentials)

        return connection.clients

My unit test looks like this:

@patch('connection.Connection.__init__')
def test_deploy(patched_connection, fs):
    patched_connection.return_value = None
    patched_connection.clients = None

    # Do some stuff

The question is... how do I set the clients property in my test as the method under test requires it to be set? (I can set it to None, but I just need to be able to set it.)

With the current code, my application returns the error:

AttributeError: 'Connection' object has no attribute 'clients'

Thanks!

Upvotes: 2

Views: 293

Answers (1)

MrBean Bremen
MrBean Bremen

Reputation: 16885

You probably want to patch the Connection class itself, not the __init__ method:

@patch('connection.Connection')
def test_deploy(patched_connection, fs):
    connection_object = MagicMock()
    patched_connection.return_value = connection_object
    connection_object.clients = None
    sut = Auth()  # create the tested object (Auth is a placeholder here)
    sut._auth('')  # call the tested function

    # test for how `Connection` was constructed 
    patched_connection.assert_called_once_with(
        base_url='https://someurl.com', creds='')

You patch the Connection class, and by setting return_value you set the Connection instance mock. Now you can set the wanted attributes in that instance.

Note that checking for the __init__ call actually means to check for the instance creation call, so you can use the Connection mock for that.

This is presuming that you don't want to test Connection itself, of course, and that _auth belongs to another class (here called Auth).

Upvotes: 2

Related Questions