Testing LDAP connections

LDAP mocks - directory lookups, searches, empty results and multiple entries.

When your Zato service looks up users in Active Directory, authenticates against LDAP, or queries organizational data, you need to test that logic without a real directory server. This page shows how to mock LDAP responses so your tests run fast and don't require directory access.

Note: If you're new to unit testing with Zato, check the tutorial first.

Basic usage

Services access LDAP connections like this:

from zato.server.service import Service

class GetUserFromLDAP(Service):
    name = 'ldap.user.get'
    input = 'email'

    def handle(self):
        conn = self.out.ldap['corporate-directory'].conn
        entries = conn.get(self.request.input.email)

        if entries:
            user = entries[0]
            self.response.payload = {
                'name': user['cn'],
                'email': user['mail'],
                'department': user['department']
            }
        else:
            self.response.payload = {'error': 'User not found'}

Mock the LDAP results in your test:

from zato_testing import ServiceTestCase
from myapp.services import GetUserFromLDAP

class TestGetUserFromLDAP(ServiceTestCase):

    def test_returns_user(self):

        # Configure LDAP results with ldap: prefix
        self.set_response('ldap:corporate-directory', [
            {
                'cn': 'John Smith',
                'mail': 'john.smith@example.com',
                'department': 'Engineering'
            }
        ])

        service = self.invoke(GetUserFromLDAP, email='john.smith@example.com')

        self.assertEqual(service.response.payload['name'], 'John Smith')
        self.assertEqual(service.response.payload['department'], 'Engineering')

Note the ldap: prefix to distinguish LDAP connections from REST connections.

Mock search operations:

class SearchUsers(Service):
    name = 'ldap.users.search'
    input = 'department'

    def handle(self):
        conn = self.out.ldap['corporate-directory'].conn
        entries = conn.search(
            filter=f'(department={self.request.input.department})'
        )

        self.response.payload = {
            'users': [{'name': e['cn'], 'email': e['mail']} for e in entries]
        }
class TestSearchUsers(ServiceTestCase):

    def test_finds_users_in_department(self):

        self.set_response('ldap:corporate-directory', [
            {'cn': 'Alice', 'mail': 'alice@example.com'},
            {'cn': 'Bob', 'mail': 'bob@example.com'},
            {'cn': 'Carol', 'mail': 'carol@example.com'}
        ])

        service = self.invoke(SearchUsers, department='Engineering')

        self.assertEqual(len(service.response.payload['users']), 3)

Empty results

Test handling of users not found:

class TestUserNotFound(ServiceTestCase):

    def test_handles_missing_user(self):

        self.set_response('ldap:corporate-directory', [])

        service = self.invoke(GetUserFromLDAP, email='unknown@example.com')

        self.assertEqual(service.response.payload['error'], 'User not found')

Multiple entries

Return multiple LDAP entries:

class TestMultipleEntries(ServiceTestCase):

    def test_returns_all_matches(self):

        self.set_response('ldap:corporate-directory', [
            {'cn': 'John Smith', 'mail': 'john.smith@example.com'},
            {'cn': 'John Doe', 'mail': 'john.doe@example.com'},
            {'cn': 'John Adams', 'mail': 'john.adams@example.com'}
        ])

        service = self.invoke(SearchUsers, name='John*')

        self.assertEqual(len(service.response.payload['users']), 3)

Learn more