ForcePilot/backend/test/unit/external_systems/integrations/test_discovery.py
Kris 15c1cd95ba test: 新增并完善外部系统单元测试覆盖
- 新增多个集成服务(Slack、Notion、Twilio、Microsoft365等)的元数据、常量、凭证、错误处理相关单元测试
- 新增持久化适配器、工作单元、健康检查仓储的单元测试
- 修复认证插件测试中缺失的凭证类型注册
- 修正密钥轮换调度器的异常类型匹配
- 完善审计日志测试用例,新增创建者/更新者字段校验
- 新增告警触发时持久化通知渠道的测试
- 精简核心模型测试代码,移除冗余的超时测试用例
2026-07-11 05:42:04 +08:00

209 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 == []