Skip to main content

A pytest plugin for mocking Clerk authentication

Project description

pytest-clerk-mock

A pytest plugin for mocking Clerk authentication in your tests.

Installation

pip install pytest-clerk-mock

Or with Poetry:

poetry add --group dev pytest-clerk-mock

Usage

The plugin provides a mock_clerk fixture that you can use in your tests:

def test_create_user(mock_clerk):
    user = mock_clerk.users.create(
        email_address=["test@example.com"],
        first_name="John",
        last_name="Doe",
    )

    assert user.id is not None
    assert user.first_name == "John"

    fetched = mock_clerk.users.get(user.id)
    assert fetched.email_addresses[0].email_address == "test@example.com"

Async API

All methods have async variants with an _async suffix, matching the clerk-backend-api SDK:

async def test_create_user_async(mock_clerk):
    user = await mock_clerk.users.create_async(
        email_address=["test@example.com"],
        first_name="John",
        last_name="Doe",
    )

    assert user.id is not None

    fetched = await mock_clerk.users.get_async(user_id=user.id)
    assert fetched.first_name == "John"

For SDK parity, several async methods are keyword-only (for example: get_async(user_id=...), update_async(user_id=...), delete_async(user_id=...)).

Authentication

The mock client provides full authentication state management:

Configure Auth State

def test_with_auth(mock_clerk):
    mock_clerk.configure_auth("user_123", org_id="org_456", org_role="org:admin")

    result = mock_clerk.authenticate_request(request, options)
    assert result.is_signed_in
    assert result.payload["sub"] == "user_123"

Temporary User Context

Use the as_user context manager to temporarily switch users:

def test_as_different_user(mock_clerk):
    with mock_clerk.as_user("user_456", org_id="org_789"):
        result = mock_clerk.authenticate_request(request, options)
        assert result.payload["sub"] == "user_456"

Predefined User Types

Use MockClerkUser for common test scenarios:

from pytest_clerk_mock import MockClerkUser

def test_with_predefined_user(mock_clerk):
    with mock_clerk.as_clerk_user(MockClerkUser.TEAM_OWNER, org_id="org_123"):
        # Authenticated as team owner
        pass

    with mock_clerk.as_clerk_user(MockClerkUser.GUEST):
        # Authenticated as guest
        pass

Available predefined users:

  • MockClerkUser.TEAM_OWNER
  • MockClerkUser.TEAM_MEMBER
  • MockClerkUser.GUEST
  • MockClerkUser.UNAUTHENTICATED

Organizations

from clerk_backend_api.models import ClerkErrors

def test_organizations(mock_clerk):
    mock_clerk.organizations.add("org_123", name="My Organization", slug="my-org")

    org = mock_clerk.organizations.get("org_123")
    assert org.name == "My Organization"

    with pytest.raises(ClerkErrors):
        mock_clerk.organizations.get("org_missing")

Organization Memberships

Use the SDK-style organization_memberships API for org membership lifecycle:

def test_organization_memberships(mock_clerk):
    membership = mock_clerk.organization_memberships.create(
        organization_id="org_123",
        user_id="user_123",
        role="org:admin",
    )

    assert membership.organization_id == "org_123"
    assert membership.user_id == "user_123"
    assert membership.role == "org:admin"

    memberships = mock_clerk.organization_memberships.list(
        organization_id="org_123",
        user_id=["user_123"],
    )
    assert memberships.total_count == 1
    assert memberships.data[0].user_id == "user_123"

If your app reads memberships via users.get_organization_memberships(...), configure that explicitly:

from pytest_clerk_mock import MockOrganizationMembershipsResponse

def test_user_membership_lookup(mock_clerk):
    mock_clerk.users.set_organization_memberships(
        "user_123",
        MockOrganizationMembershipsResponse(data=[], total_count=0),
    )
    memberships = mock_clerk.users.get_organization_memberships("user_123")
    assert memberships.total_count == 0

Custom Fixture Configuration

Create a custom fixture with different defaults:

# conftest.py
from pytest_clerk_mock import create_mock_clerk_fixture

mock_clerk = create_mock_clerk_fixture(
    default_user_id="user_custom",
    default_org_id="org_custom",
    default_org_role="org:member",
    autouse=True,
)

patch_targets is accepted for backward compatibility in fixture/context-manager helpers, but is deprecated and ignored.

Context Manager API

For use outside of pytest fixtures:

from pytest_clerk_mock import mock_clerk_backend

def test_with_context_manager():
    with mock_clerk_backend(default_user_id="user_123") as mock:
        mock.configure_auth("user_456")
        # Your test code here

Supported Operations

Users

Sync Async
create() create_async()
get() get_async()
list() list_async()
update() update_async()
delete() delete_async()
count() count_async()
get_organization_memberships() get_organization_memberships_async()

Organizations

Sync Async
add() -
get() get_async()
reset() -

Organization Memberships

Sync Async
create() create_async()
list() list_async()
delete() delete_async()
reset() -

Authentication

Method Description
authenticate_request() Mock Clerk's authenticate_request
configure_auth() Set current auth state
configure_auth_from_user() Set auth using MockClerkUser
as_user() Context manager for temporary user
as_clerk_user() Context manager with MockClerkUser
add_organization_membership() Add org membership for a user
reset() Reset all mock state

Helper Functions

Low-level helpers for specific mocking scenarios:

from pytest_clerk_mock import (
    create_clerk_errors,
    mock_clerk_user_creation,
    mock_clerk_user_creation_failure,
    mock_clerk_user_exists,
)

def test_user_creation():
    with mock_clerk_user_creation("myapp.clerk.users.create_async", "user_123") as mock:
        # Your code that creates a user
        mock.assert_called_once()

def test_creation_failure():
    with mock_clerk_user_creation_failure("myapp.clerk.users.create_async"):
        # Your code that handles creation failure
        pass

def test_duplicate_email():
    with mock_clerk_user_exists(
        "myapp.clerk.users.create_async",
        "myapp.clerk.users.list_async",
        "user_existing_123",
    ) as (mock_create, mock_list):
        # Your code that handles duplicate email scenario
        pass

def test_generic_clerk_error():
    err = create_clerk_errors()
    assert err is not None

Exceptions

The mock raises appropriate exceptions matching Clerk's behavior:

  • ClerkErrors - When creating a user with a duplicate email (matches real Clerk API)
  • ClerkErrors - When getting/updating/deleting a non-existent user (uses resource_not_found)
  • ClerkErrors - When getting a non-existent organization (uses resource_not_found)
from clerk_backend_api.models import ClerkErrors

def test_user_not_found(mock_clerk):
    with pytest.raises(ClerkErrors):
        mock_clerk.users.get("nonexistent_user")

def test_duplicate_email(mock_clerk):
    mock_clerk.users.create(email_address=["test@example.com"])

    with pytest.raises(ClerkErrors):
        mock_clerk.users.create(email_address=["test@example.com"])

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytest_clerk_mock-0.2.2.tar.gz (16.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytest_clerk_mock-0.2.2-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file pytest_clerk_mock-0.2.2.tar.gz.

File metadata

  • Download URL: pytest_clerk_mock-0.2.2.tar.gz
  • Upload date:
  • Size: 16.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pytest_clerk_mock-0.2.2.tar.gz
Algorithm Hash digest
SHA256 9987e8461fde33345311c21cf0c3cb6de7acc76e7af4d2a5f75edd6906a4ccdb
MD5 28ccd7206a4a82882cdb595a268ee2f6
BLAKE2b-256 0516ddddc897be2fcdd0bf148de9fba6e83a0dc59004f5240d5a60e6da53ee5e

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clerk_mock-0.2.2.tar.gz:

Publisher: publish-to-pypi.yml on julien777z/pytest-clerk-mock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pytest_clerk_mock-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for pytest_clerk_mock-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8226f4a88fdb01f64c0fb17d44fd4cb1f682f347b8675d00c5b26918c3f50d72
MD5 78a51fd2200ef9573654be9a50b1d2a0
BLAKE2b-256 e4ae713a2b732acfdd8660daea328afde00df993de647dca629923563ba1a7bc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytest_clerk_mock-0.2.2-py3-none-any.whl:

Publisher: publish-to-pypi.yml on julien777z/pytest-clerk-mock

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page