Package: fakeldap
The goal of this module is to provide a simple way to mock ldap backend servers
for your unittests. It makes it possible to define upfront a set of directory
entries that can be queried or set fixed return values to ldap queries. It acts
as a drop in replacement for theLDAPObjectclass of the python-ldap
module. It implements a subset of the allowed methods of this class.This module implements theMockLDAPclass that functions both as theLDAPObjectas well as the ldap module. Most of the code and design has been
taken from Peter Sagerson’s excellentdjango-auth-ldapmodule.InstallationInstall the latest release from PyPI:$ pip install fakeldapRunning tests in developmentIf you’ve cloned the repository locally:$ git clone git://github.com/zulip/fakeldap.gitand made changes, ensure you havepytestinstalled:$ pip install pytestand you can run the tests with:$ pytest tests.pyUsageNoteThis code is still experimental and not very tested as of yet. So is the
documentationTheMockLDAPclass replaces theLDAPObjectof the python-ldap module.
The easiest way to use it, is to overwriteldap.initializeto returnMockLDAPinstead ofLDAPObject. The example below uses Michael Foord’sMocklibrary to achieve that:import unittest
from mock import patch
from fakeldap import MockLDAP


_mock_ldap = MockLDAP()

class YourTestCase(unittest.TestCase):
    def setUp(self):
        # Patch where the ldap library is used:
        self.ldap_patcher = patch('app.module.ldap.initialize')
        self.mock_ldap = self.ldap_patcher.start()
        self.mock_ldap.return_value = _mock_ldap

    def tearDown(self):
        _mock_ldap.reset()
        self.mock_ldap.stop()The mock ldap object implements the following ldap operations:simple_bind_ssearch_scompare_smodify_sdelete_sadd_srename_sThis is an example how to useMockLDAPwith fixed return values:def test_some_ldap_group_stuff(self):
    # Define the expected return value for the ldap operation
    return_value = ("cn=testgroup,ou=group,dc=30loops,dc=net", {
        'objectClass': ['posixGroup'],
        'cn': 'testgroup',
        'gidNumber': '2030',
    })

    # Register a return value with the MockLDAP object
    _mock_ldap.set_return_value('add_s',
        ("cn=testgroup,ou=groups,dc=30loops,dc=net", (
            ('objectClass', ('posixGroup')),
            ('cn', 'testgroup'),
            ('gidNumber', '2030'))),
        (105,[], 10, []))

    # Run your actual code, this is just an example
    group_manager = GroupManager()
    result = group_manager.add("testgroup")

    # assert that the return value of your method and of the MockLDAP
    # are as expected, here using python-nose's eq() test tool:
    self.assertEqual(return_value, result)

    # Each actual ldap call your software makes gets recorded. You could
    # prepare a list of calls that you expect to be issued and compare it:
    called_records = []

    called_records.append(('simple_bind_s',
        {'who': 'cn=admin,dc=30loops,dc=net', 'cred': 'ldaptest'}))

    called_records.append(('add_s', {
        'dn': 'cn=testgroup,ou=groups,dc=30loops,dc=net",
        'record': [
            ('objectClass', ['posixGroup']),
            ('gidNumber', '2030'),
            ('cn', 'testgroup'),
            ]}))

    # And again test the expected behaviour
    self.assertEqual(called_records, _mock_ldap.ldap_methods_called_with_arguments())Besides of fixing return values for specific calls, you can also imitate a full
ldap server with a directory of entries:# Create an instance of MockLDAP with a preset directory
tree = {
    "cn=admin,dc=30loops,dc=net": {
            "userPassword": "ldaptest"
    }
}
mock_ldap = MockLDAP(tree)

record = [
    ('uid', 'crito'),
    ('userPassword', 'secret'),
]
# The return value I expect when I add another record to the directory
self.assertEqual(
    (105,[],1,[]),
    mock_ldap.add_s("uid=crito,ou=people,dc=30loops,dc=net", record)
)

# The expected directory
directory = {
    "cn=admin,dc=30loops,dc=net": {"userPassword": "ldaptest"},
    "uid=crito,ou=people,dc=30loops,dc=net": {
        "uid": "crito", "userPassword": "secret"}
}
# Compare the expected directory with the MockLDAP directory
self.assertEqual(directory, mock_ldap.directory)