|
1 | 1 | # tests/conftest.py
|
2 | 2 | import os
|
| 3 | +import sys |
3 | 4 | import pytest
|
4 | 5 | from unittest.mock import MagicMock, patch
|
| 6 | +from typing import Dict, Any |
5 | 7 |
|
6 |
| -# Mock clickhouse module globally before any imports |
7 |
| -@pytest.fixture(scope="session", autouse=True) |
8 |
| -def mock_clickhouse_modules(): |
9 |
| - """Mock clickhouse modules at the import level to prevent any connection attempts.""" |
| 8 | +# Apply global patches before any app modules are imported |
| 9 | +def pytest_configure(config): |
| 10 | + """Configure test environment before any test modules are loaded.""" |
| 11 | + # Mock out third-party modules that try to make connections |
10 | 12 | modules_to_mock = [
|
11 | 13 | "clickhouse_connect",
|
12 |
| - "clickhouse_connect.get_client", |
13 | 14 | "clickhouse_driver",
|
| 15 | + "asyncpg", |
| 16 | + "celery", |
| 17 | + "celery.app", |
14 | 18 | ]
|
15 | 19 |
|
16 |
| - # Create module level mocks |
17 |
| - mocks = {} |
18 | 20 | for module_name in modules_to_mock:
|
19 |
| - mock = MagicMock() |
20 |
| - mocks[module_name] = mock |
21 |
| - |
22 |
| - # Apply patches |
23 |
| - patches = [] |
24 |
| - for module_name, mock in mocks.items(): |
25 |
| - patcher = patch(module_name, mock) |
26 |
| - patches.append(patcher) |
27 |
| - patcher.start() |
28 |
| - |
29 |
| - # Mock get_client function specifically |
30 |
| - mock_client = MagicMock() |
31 |
| - mocks["clickhouse_connect"].get_client.return_value = mock_client |
32 |
| - |
33 |
| - # Allow test to run |
34 |
| - yield mocks |
35 |
| - |
36 |
| - # Remove patches after tests complete |
37 |
| - for patcher in patches: |
38 |
| - patcher.stop() |
| 21 | + if module_name not in sys.modules: |
| 22 | + sys.modules[module_name] = MagicMock() |
| 23 | + |
| 24 | + # Mock specific functions |
| 25 | + sys.modules["clickhouse_connect"].get_client = MagicMock(return_value=MagicMock()) |
| 26 | + |
| 27 | +# Mock Settings class before it's imported |
| 28 | +@pytest.fixture(scope="session", autouse=True) |
| 29 | +def mock_settings(): |
| 30 | + """Mock the Settings class to avoid validation errors.""" |
| 31 | + # Create a fake settings object with all required attributes |
| 32 | + mock_settings = MagicMock() |
| 33 | + |
| 34 | + # Add all required attributes |
| 35 | + settings_attrs = [ |
| 36 | + "PROJECT_NAME", "API_V1_STR", "POSTGRES_SERVER", "POSTGRES_USER", |
| 37 | + "POSTGRES_PASSWORD", "POSTGRES_DB", "SQLALCHEMY_DATABASE_URI", |
| 38 | + "BROKER_USER", "BROKER_PASSWORD", "BROKER_HOST", "BROKER_PORT", |
| 39 | + "BROKER_VHOST", "CELERY_BROKER_URL", "CELERY_RESULT_BACKEND", |
| 40 | + "CLICKHOUSE_HOST", "CLICKHOUSE_USERNAME", "CLICKHOUSE_PASSWORD", |
| 41 | + "CLICKHOUSE_DATABASE", "JAEGER_URL", "SUPER_ADMIN_EMAIL", |
| 42 | + "SUPER_ADMIN_USERNAME", "SUPER_ADMIN_PASSWORD" |
| 43 | + ] |
| 44 | + |
| 45 | + # Set attributes to test values |
| 46 | + for attr in settings_attrs: |
| 47 | + setattr(mock_settings, attr, f"test_{attr.lower()}") |
| 48 | + |
| 49 | + # Special handling for database URIs |
| 50 | + mock_settings.SQLALCHEMY_DATABASE_URI = "postgresql+asyncpg://postgres:postgres@localhost:5432/postgres" |
| 51 | + |
| 52 | + # Apply the patch |
| 53 | + with patch("app.core.config.Settings", return_value=mock_settings): |
| 54 | + with patch("app.core.config.settings", mock_settings): |
| 55 | + yield mock_settings |
39 | 56 |
|
40 | 57 | @pytest.fixture(scope="session", autouse=True)
|
41 | 58 | def setup_env():
|
42 | 59 | """Setup environment variables for tests."""
|
43 |
| - # Set default environment variables if not present |
| 60 | + # Ensure critical environment variables are set |
44 | 61 | os.environ.setdefault("PROJECT_NAME", "Test Project")
|
| 62 | + |
| 63 | + # Database env vars |
| 64 | + os.environ.setdefault("POSTGRES_SERVER", "mock") |
| 65 | + os.environ.setdefault("POSTGRES_USER", "postgres") |
| 66 | + os.environ.setdefault("POSTGRES_PASSWORD", "postgres") |
| 67 | + os.environ.setdefault("POSTGRES_DB", "postgres") |
| 68 | + |
| 69 | + # Broker env vars |
| 70 | + os.environ.setdefault("BROKER_USER", "guest") |
| 71 | + os.environ.setdefault("BROKER_PASSWORD", "guest") |
| 72 | + os.environ.setdefault("BROKER_HOST", "localhost") |
| 73 | + os.environ.setdefault("BROKER_PORT", "5672") |
| 74 | + os.environ.setdefault("BROKER_VHOST", "/") |
| 75 | + |
| 76 | + # ClickHouse env vars |
45 | 77 | os.environ.setdefault("CLICKHOUSE_HOST", "mock")
|
| 78 | + os.environ.setdefault("CLICKHOUSE_USERNAME", "default") |
| 79 | + os.environ.setdefault("CLICKHOUSE_PASSWORD", "") |
| 80 | + os.environ.setdefault("CLICKHOUSE_DATABASE", "default") |
46 | 81 |
|
47 |
| - # Ensure critical environment variables are set |
48 |
| - assert os.getenv("PROJECT_NAME"), "Project Name not set in the env" |
| 82 | + # Other required env vars |
| 83 | + os.environ.setdefault("JAEGER_URL", "http://localhost:14268/api/traces") |
| 84 | + os.environ.setdefault("SUPER_ADMIN_EMAIL", "admin@example.com") |
| 85 | + os.environ.setdefault("SUPER_ADMIN_USERNAME", "admin") |
| 86 | + os.environ.setdefault("SUPER_ADMIN_PASSWORD", "admin") |
49 | 87 |
|
50 | 88 | yield
|
51 | 89 |
|
| 90 | +# Mock database and external connections |
| 91 | +@pytest.fixture(autouse=True) |
| 92 | +def mock_external_connections(monkeypatch): |
| 93 | + """Mock all external connections.""" |
| 94 | + # Mock SQLAlchemy |
| 95 | + monkeypatch.setattr("sqlalchemy.create_engine", MagicMock()) |
| 96 | + monkeypatch.setattr("sqlalchemy.ext.asyncio.create_async_engine", MagicMock()) |
| 97 | + |
| 98 | + # Mock asyncpg connections |
| 99 | + if "asyncpg" in sys.modules: |
| 100 | + monkeypatch.setattr("asyncpg.connect", MagicMock()) |
| 101 | + monkeypatch.setattr("asyncpg.create_pool", MagicMock()) |
| 102 | + |
| 103 | + # Mock Celery |
| 104 | + if "celery" in sys.modules: |
| 105 | + monkeypatch.setattr("celery.Celery", MagicMock()) |
| 106 | + |
52 | 107 | # Example async fixture if needed for other tests
|
53 | 108 | @pytest.fixture
|
54 | 109 | async def async_fixture():
|
|
0 commit comments