本次提交清理了多个单元测试文件中的多余空行,调整了部分导入的顺序,同时修复了一处feishu错误翻译的导入顺序问题,移除了application/conftest.py中未使用的fake_report_repo fixture,优化代码格式提升可读性。
132 lines
3.6 KiB
Python
132 lines
3.6 KiB
Python
"""yuxi.channels.adapters.masking_adapter 单元测试。
|
||
|
||
覆盖 ``MaskingAdapter`` 的 ``mask_full`` / ``mask_partial`` /
|
||
``is_sensitive_key`` 方法,使用 ``patch`` 替换 ``CryptoHelper``,
|
||
不依赖真实加解密配置。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from unittest.mock import MagicMock, patch
|
||
|
||
import pytest
|
||
from yuxi.channels.adapters.masking_adapter import MaskingAdapter
|
||
|
||
pytestmark = pytest.mark.unit
|
||
|
||
|
||
def _make_helper() -> MagicMock:
|
||
"""构造 CryptoHelper 桩。"""
|
||
helper = MagicMock()
|
||
helper.mask_full = MagicMock(return_value="***")
|
||
helper.mask_partial = MagicMock(return_value="abcd***")
|
||
helper.is_sensitive_key = MagicMock(return_value=True)
|
||
return helper
|
||
|
||
|
||
@pytest.mark.unit
|
||
class TestMaskingAdapterConstruction:
|
||
def test_init_loads_crypto_helper(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
|
||
# Act
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Assert
|
||
assert adapter._helper is helper
|
||
|
||
|
||
@pytest.mark.unit
|
||
class TestMaskingAdapterMaskFull:
|
||
def test_mask_full_delegates_to_helper(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Act
|
||
result = adapter.mask_full("secret-value")
|
||
|
||
# Assert
|
||
helper.mask_full.assert_called_once_with("secret-value")
|
||
assert result == "***"
|
||
|
||
def test_mask_full_passes_any_value_type(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
helper.mask_full.return_value = {"masked": True}
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Act
|
||
result = adapter.mask_full({"key": "value"})
|
||
|
||
# Assert
|
||
helper.mask_full.assert_called_once_with({"key": "value"})
|
||
assert result == {"masked": True}
|
||
|
||
|
||
@pytest.mark.unit
|
||
class TestMaskingAdapterMaskPartial:
|
||
def test_mask_partial_delegates_to_helper(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Act
|
||
result = adapter.mask_partial("token-value")
|
||
|
||
# Assert
|
||
helper.mask_partial.assert_called_once_with("token-value")
|
||
assert result == "abcd***"
|
||
|
||
|
||
@pytest.mark.unit
|
||
class TestMaskingAdapterIsSensitiveKey:
|
||
def test_is_sensitive_key_delegates_to_helper(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Act
|
||
result = adapter.is_sensitive_key("api_key")
|
||
|
||
# Assert
|
||
helper.is_sensitive_key.assert_called_once_with("api_key")
|
||
assert result is True
|
||
|
||
def test_is_sensitive_key_returns_false_for_non_sensitive(self):
|
||
# Arrange
|
||
helper = _make_helper()
|
||
helper.is_sensitive_key.return_value = False
|
||
with patch(
|
||
"yuxi.channels.adapters.masking_adapter.get_crypto_helper",
|
||
return_value=helper,
|
||
):
|
||
adapter = MaskingAdapter()
|
||
|
||
# Act
|
||
result = adapter.is_sensitive_key("display_name")
|
||
|
||
# Assert
|
||
assert result is False
|