# 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](https://zato.io/docs/api-testing/tutorial.html) first.

## Basic usage {#basic-usage}

Services access LDAP connections like this:

```python
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:

```python
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.

## LDAP search {#ldap-search}

Mock search operations:

```python
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]
        }
```

```python
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 {#empty-results}

Test handling of users not found:

```python
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 {#multiple-entries}

Return multiple LDAP entries:

```python
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 {#learn-more}

- [API testing](https://zato.io/docs/api-testing/) - Tests in plain English, run against real or mocked connections
- [API testing tutorial](https://zato.io/docs/api-testing/tutorial.html) - A complete test suite, from the first scenario to the report
- [Testing REST connections](https://zato.io/docs/api-testing/rest.html) - Mock outgoing REST calls and assert on what your service sent
- [Testing SQL connections](https://zato.io/docs/api-testing/sql.html) - Mock database queries and the rows they return
- [Testing Microsoft 365](https://zato.io/docs/api-testing/ms365/) - Mock mailboxes, calendars, SharePoint, Teams and the rest
- [Testing service invocations](https://zato.io/docs/api-testing/services.html) - Services that call other services, with the callees mocked
- [Testing Jira connections](https://zato.io/docs/api-testing/jira.html) - Mock Jira API calls and the issues they return
- [Tests in CI/CD](https://zato.io/docs/api-testing/ci-cd.html) - Running the suite in a pipeline and reading its output
