Files
JQC_multi_tenant/tests/test_tenant_routing.py
T

41 lines
1.5 KiB
Python

"""
Tests for the tenant routing layer (app/tenancy/routing.py).
The crown-jewel invariant of the multi-tenant design is data isolation: a
request bound to tenant A must never touch tenant B's database. Full isolation
proof requires two live tenant DBs and belongs in an integration suite (see
tests/README.md). What we CAN verify cheaply and deterministically here is the
other half of the contract:
"The routing layer is completely inert until a tenant is resolved."
If routing were NOT inert when MULTI_TENANT_ENABLED=false, the existing
single-tenant deployment would break. This test locks that guarantee in.
"""
from flask import g
def test_routing_is_inert_without_a_resolved_tenant(app):
"""With no g.tenant_engine set, db.session binds to the default engine."""
from app import db
with app.test_request_context('/'):
# Multi-tenancy disabled → the resolver never sets g.tenant_engine.
assert g.get('tenant_engine') is None
# …so get_bind() must fall through to the app's default engine.
assert db.session.get_bind() is db.engine
def test_resolved_tenant_engine_wins(app, monkeypatch):
"""When g.tenant_engine IS set, get_bind() returns it, not the default."""
from app import db
class _SentinelEngine:
"""Stand-in object; get_bind should return it verbatim when present."""
sentinel = _SentinelEngine()
with app.test_request_context('/'):
g.tenant_engine = sentinel
assert db.session.get_bind() is sentinel