Mock Directories¶
The first step to using mockldap is to define some static LDAP content and
install it as a mock LDAPObject
. For this, you will use
mockldap.MockLdap
. Only one instance of this class should exist at a
time; setUpClass()
is a good place to instantiate it.
MockLdap
can mock multiple LDAP directories, identified by
URI. You can provide directory content for URIs individually and you can also
provide default content for connections to any unrecognized URI. If the code
under test is only expected to make one LDAP connection, the simplest option is
just to provide default content. If you need multiple directories, you can call
set_directory()
on your MockLdap
instance.
LDAP content takes the form of a Python dictionary. Each key is a distinguished
name in string form; each value is a dictionary mapping attributes to lists of
values. In other words, directory.items()
should take the same form as
results from search_s()
.
directory = {
'uid=alice,ou=people,o=test': {
'uid': ['alice'],
'objectClass': ['person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount'],
'userPassword': ['password'],
'uidNumber': ['1000'],
'gidNumber': ['1000'],
'givenName': ['Alice'],
'sn': ['Adams']
},
'cn=active,ou=groups,o=test': {
'cn': ['active'],
'objectClass': ['groupOfNames'],
'member': ['uid=alice,ou=people,o=test']
},
}
MockLdap
is stateful. The overview shows a complete
example, but following are the enumerated steps.
For some collection of tests:
- Instantiate
MockLdap
. Optionally pass in default directory contents.Add content
for any additional directories. This is only necessary if the code under test will connect to multiple LDAP directories.
For each test:
- Just before an individual test, call
start()
. This will instantiate your mock directories and patchldap.initialize()
. You may need to call this multiple times ifinitialize()
is accessed by multiple names.- Any time during your test, you can access an individual
LDAPObject
asmockldap[uri]
. This will let you seed return values for LDAP operations and recover the record of which operations were performed.- After the test, call
stop()
orstop_all()
.
Warning
The code under test must not keep an LDAP “connection” open across
individual test cases. If it does, it will be sharing a mock
LDAPObject
across tests, so any state mutations will
persist.
MockLdap¶
-
class
mockldap.
MockLdap
(directory=None)[source]¶ Top-level class managing directories and patches.
Parameters: directory – Default directory contents. After calling
start()
,mockldap[uri]
returns anLDAPObject
. This is the same object that will be returned byldap.initialize(uri)
, so you can use it to seed return values and discover which APIs were called.MockLdap objects may be used as context managers in place of calling
start()
andstop()
manually. The import path forldap.initialize
can not be overridden in this case.-
set_directory
(directory, uri='__default__')[source]¶ Set the mock LDAP content for a given URI.
Parameters: uri (string) – The LDAP URI to associate this content with. If URI is not given, this will set the default content for all unknown URIs.
-
start
(path='ldap.initialize')[source]¶ Patch
ldap.initialize()
to return mock LDAPObject instances.This calls
mock.patch()
, so under Python 2, you must have the mock library installed.Parameters: path (string) – The module path to ldap.initialize
.If the code under test looks like:
import ldap ... ldap.initialize(uri)
then you can use the default value of path. If the code reads:
from ldap import initialize ... initialize(uri)
then you need to call
start('path.to.your.mod.initialize')
. See Where to patch for more.
-
stop
(path='ldap.initialize')[source]¶ Stop patching
ldap.initialize()
.Calls to
start()
andstop()
must be balanced. After the final call to stop, we’ll reset allLDAPObject
instances.
-