Using ldap_faker with unittest

Most of the purpose of python-ldap-faker is to make automated testing of code that uses python-ldap easier.

To this end, python-ldap-faker provides LDAPFakerMixin, a mixin class for unittest.TestCase which handles all the hard work of patching and instrumenting the appropriate python-ldap functions, objects and methods.

LDAPFakerMixin will do the following things for you:

Configuring your LDAPFakerMixin TestCase

We need to set two class attributes on LDAPFakerMixin in order for it to properly set up your tests:

LDAPFakerMixin.ldap_modules

LDAPFakerMixin uses unittest.mock.patch to patch your code so that it uses our fake versions of ldap.initialize, ldap.set_option and ldap.get_option instead of the real one. The way patch works is that it must apply the patch within the context of your module that does import ldap, not within the ldap module itself. Thus, to make LDAPFakerMixin work for you, you must list all the modules for code under test in which you do import ldap.

To list all the modules in which the code under test does import ldap, use the LDAPFakerMixin.ldap_modules class attribute.

For example, if you have a class MyLDAPUsingClass in the module myapp.myldapstuff, and you do import ldap in myapp.myldapstuff, for instance:

import ldap

class MyLDAPUsingClass:

    def connect(self, uid: str, password: str):
        self.conn = ldap.initialize('ldap://server')
        self.conn.set_option(ldap.OPT_X_TLS_NEWCTX, 0)
        self.conn.start_tls_s()
        self.conn.simple_bind_s(
          f'uid={uid},ou=bar,o=baz,c=country',
          'the password'
        )

To test this code, you would use this for ldap_modules:

import unittest
from ldap_faker import LDAPFakerMixin

from myapp.myldapstuff import MyLDAPUsingClass

class TestMyLDAPUsingCLass(LDAPFakerMixin, unittest.TestCase):

    ldap_modules = ['myapp.myldapstuff']

LDAPFakerMixin.ldap_fixtures

In order to effectively test your python-ldap using code, you’ll need to populate an LDAPServerFactory one or more ObjectStore objects bound to LDAP URIs. We use LDAPFakerMixin.ldap_fixtures to declare file paths to fixture files to use to populate those ObjectClass objects.

You can configure your LDAPFakerMixin to use fixtures one of two ways:

  • Use a single default fixture that will be used no matter which LDAP URI is passed to FakeLDAP.initialize

  • Bind each fixture to specific a LDAP URI. This allows you simulate talking to several different LDAP servers.

Note

When binding fixtures to particular LDAP URIs, if your tries to use FakeLDAP.initialize with an LDAP URI that was not explicitly configured, python-ldap-faker will raise ldap.SERVER_DOWN

This form sets up one default fixture:

import unittest
from ldap_faker import LDAPFakerMixin

from myapp.myldapstuff import MyLDAPUsingClass

class TestMyLDAPUsingCLass(LDAPFakerMixin, unittest.TestCase):

    ldap_fixtures = 'objects.json'

This form binds fixtures to LDAP URIs:

import unittest
from ldap_faker import LDAPFakerMixin

from myapp.myldapstuff import MyLDAPUsingClass

class TestMyLDAPUsingCLass(LDAPFakerMixin, unittest.TestCase):

    ldap_fixtures = [
      ('server1.json', 'ldap://server1.example.com'),
      ('server2.json', 'ldap://server2.example.com')
    ]

Test isolation

Each test method on your unittest.TestCase will get a fresh, unaltered copy of the fixture data, and connections, call histories, options set from previous test methods will be cleared.

Test support offered by LDAPFakerMixin

For each test you run, your test will have access to the FakeLDAP instance used for that test through the LDAPFakerMixin.fake_ldap instance attribute. Each test gets a fresh FakeLDAP instance.

Note

For detailed information on any of the below, see the Developer Interface.

Some things to know about your FakeLDAP instance:

Some things to know about the FakeLDAPObject objects in FakeLDAP.connections: