ForcePilot/backend/test/unit/external_systems/integrations/test_discovery.py
Kris 08617091dc refactor: 整理项目包结构与导入路径
- 新增多个业务域的__init__.py模块文件,规范包导出结构
- 调整多个DTO文件的导入路径,统一模块组织方式
- 移除测试文件中多余的空行与导入语句
- 优化部分业务模块的包层级划分
2026-07-18 02:04:03 +08:00

207 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""integrations/discovery.py 自动发现单元测试。
覆盖 discover_integration_packages() 的黑名单跳过、非包跳过、下划线前缀跳过、
ImportError 容错与非 ImportError 异常透传。
通过 monkeypatch 模拟 pkgutil.iter_modules 与 importlib.import_module 返回值,
避免触发真实集成包导入副作用auth_plugins 等会向全局注册表写入不同实例导致冲突)。
"""
from __future__ import annotations
import logging
from types import ModuleType
import pytest
from yuxi.external_systems.integrations import discovery
# ─── 黑名单 ───────────────────────────────────────────────────────────────
@pytest.mark.unit
def test_blacklist_includes_infrastructure_modules():
# Arrange / Act / Assert - 框架自身模块应在黑名单中
assert "registry" in discovery._BLACKLIST
assert "schemas" in discovery._BLACKLIST
assert "discovery" in discovery._BLACKLIST
assert "operation_registry" in discovery._BLACKLIST
@pytest.mark.unit
def test_blacklist_excludes_real_integration_packages():
# Arrange / Act / Assert - 真实厂商集成包不应在黑名单中
assert "salesforce" not in discovery._BLACKLIST
assert "hubspot" not in discovery._BLACKLIST
assert "jira" not in discovery._BLACKLIST
assert "slack" not in discovery._BLACKLIST
# ─── discover_integration_packages ────────────────────────────────────────
@pytest.mark.unit
def test_discoverIntegrationPackages_skips_non_package_modules(monkeypatch):
# Arrange - 模拟 iter_modules 返回非包项
def _mock_iter_modules(_path):
yield (None, "not_a_package", False)
yield (None, "real_package", True)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
imported: list[str] = []
def _mock_import_module(name):
imported.append(name)
return ModuleType(name)
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
result = discovery.discover_integration_packages()
# Assert - 非包项ispkg=False应被跳过
assert "yuxi.external_systems.integrations.not_a_package" not in imported
assert "yuxi.external_systems.integrations.real_package" in imported
assert "yuxi.external_systems.integrations.real_package" in result
@pytest.mark.unit
def test_discoverIntegrationPackages_skips_underscore_prefixed(monkeypatch):
# Arrange
def _mock_iter_modules(_path):
yield (None, "_private", True)
yield (None, "salesforce", True)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
imported: list[str] = []
def _mock_import_module(name):
imported.append(name)
return ModuleType(name)
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
discovery.discover_integration_packages()
# Assert - 下划线前缀应被跳过
assert "yuxi.external_systems.integrations._private" not in imported
assert "yuxi.external_systems.integrations.salesforce" in imported
@pytest.mark.unit
def test_discoverIntegrationPackages_skips_blacklisted_modules(monkeypatch):
# Arrange
def _mock_iter_modules(_path):
yield (None, "registry", True)
yield (None, "schemas", True)
yield (None, "discovery", True)
yield (None, "operation_registry", True)
yield (None, "salesforce", True)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
imported: list[str] = []
def _mock_import_module(name):
imported.append(name)
return ModuleType(name)
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
discovery.discover_integration_packages()
# Assert - 黑名单模块应被跳过
for bl in ("registry", "schemas", "discovery", "operation_registry"):
assert f"yuxi.external_systems.integrations.{bl}" not in imported
assert "yuxi.external_systems.integrations.salesforce" in imported
@pytest.mark.unit
def test_discoverIntegrationPackages_logs_warning_on_importError(monkeypatch, caplog):
# Arrange
def _mock_iter_modules(_path):
yield (None, "broken_pkg", True)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
def _mock_import_module(name):
raise ImportError(f"missing dependency for {name}")
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
with caplog.at_level(logging.WARNING):
result = discovery.discover_integration_packages()
# Assert - ImportError 应被捕获并记录警告,不向上抛出;失败包不计入返回
assert any("broken_pkg" in r.message and "加载失败" in r.message for r in caplog.records)
assert result == []
@pytest.mark.unit
def test_discoverIntegrationPackages_propagates_non_import_errors(monkeypatch):
# Arrange
def _mock_iter_modules(_path):
yield (None, "bad_pkg", True)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
def _mock_import_module(name):
raise RuntimeError("unexpected metadata error")
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act / Assert - 非 ImportError 应向上抛出
with pytest.raises(RuntimeError, match="unexpected metadata error"):
discovery.discover_integration_packages()
@pytest.mark.unit
def test_discoverIntegrationPackages_returns_imported_module_names(monkeypatch):
# Arrange
def _mock_iter_modules(_path):
yield (None, "pkg_a", True)
yield (None, "pkg_b", True)
yield (None, "pkg_c", False) # 非包,跳过
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
def _mock_import_module(name):
return ModuleType(name)
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
result = discovery.discover_integration_packages()
# Assert - 返回成功导入的模块名列表
assert result == [
"yuxi.external_systems.integrations.pkg_a",
"yuxi.external_systems.integrations.pkg_b",
]
@pytest.mark.unit
def test_discoverIntegrationPackages_empty_when_all_skipped(monkeypatch):
# Arrange - 全部被跳过
def _mock_iter_modules(_path):
yield (None, "registry", True)
yield (None, "_private", True)
yield (None, "not_pkg", False)
monkeypatch.setattr(discovery.pkgutil, "iter_modules", _mock_iter_modules)
def _mock_import_module(name):
raise AssertionError(f"不应导入 {name}")
monkeypatch.setattr(discovery.importlib, "import_module", _mock_import_module)
# Act
result = discovery.discover_integration_packages()
# Assert
assert result == []