pythonunit-testingpython-unittestpython-unittest.mockldap3

Python Mock patch ldap3 search response


I am trying to mock the below function but I'm not sure how to mock the Connection response:

def get_user_res(user, pass):
    res = None
    server = Server('my_server')
    connnection = Connection(server, user, pass, strategy=SAFE_SYNC, auto_bind=True)
    if connection.bind():
        connection.search(search_base, search_filter, SUBTREE)
        res = connection.response
        connection.unbind()
    return res
@mock.patch("ldap3.Server")
@mock.patch("ldap3.Connection.response")
def test_get_user_res(mock_connection, mock_server):
    mock_connection.return_value = ""
    retrived_res = get_user_res("fake_user","fake_password")
    expected_res = ""
    assert retrived_res == expected_res

Solution

  • The root problem is that you're mocking the wrong things. If you have a file named ldapclient.py that contains your get_user_rest method, like this (note that I've rewritten things a bit to make our lives easier when writing tests):

    import ldap3
    
    server = ldap3.Server('my_server')
    search_base = 'dc=example, dc=com'
    
    
    def get_user_res(user, password, search_filter=None):
        res = None
    
        connection = ldap3.Connection(
            server, user, password,
            client_strategy=ldap3.SAFE_SYNC, auto_bind=True)
    
        if connection.bind():
            res = connection.search(search_base, search_filter, ldap3.SUBTREE)
            connection.unbind()
    
        return res
    

    Then what you need to mock is the ldap3.Connection class. But since your test is in a different module, you'll need to call @mock.patch('ldapclient.ldap3.Connection), assuming that your test is defined like this:

    import ldap3
    
    from unittest import mock
    
    import ldapclient
    
    
    @mock.patch("ldapclient.ldap3.Connection")
    def test_get_user_res(mock_connection_class):
        mock_connection = mock.Mock()
        mock_connection.search.return_value = 'fake_return'
        mock_connection_class.return_value = mock_connection
    
        retrived_res = ldapclient.get_user_res("fake_user", "fake_password")
        expected_res = "fake_return"
        assert retrived_res == expected_res
    

    There are a few things to note here:

    1. As mentioned earlier, because we have import ldapclient, we need to mock ldapclient.ldap3.Connection.
    2. We make the ldap3.Connection class return a new mock.Mock object, since we want to be able to mock methods on the object returned when calling connection = ldap3.Connection(...)
    3. We make the search method return a fake value so that we can ensure it gets called as expected.