util-resolve-serviceresult-errors
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseResolve ServiceResult Errors
解决ServiceResult错误
Purpose
目的
Systematic diagnostic and fix workflow for ServiceResult pattern mistakes in tests and service implementations, focusing on mock configuration errors, async patterns, and type safety.
针对测试和服务实现中ServiceResult模式问题的系统化诊断与修复流程,重点关注mock配置错误、异步模式和类型安全。
Quick Start
快速开始
Diagnose and fix common mistakes when working with the ServiceResult pattern in project-watch-mcp, focusing on test failures caused by incorrect mock configurations and improper ServiceResult usage.
Most common use case:
bash
undefined诊断并修复project-watch-mcp中使用ServiceResult模式时的常见问题,重点解决由不正确的mock配置和不规范的ServiceResult使用导致的测试失败。
最常见使用场景:
bash
undefinedTest fails with: 'dict' object has no attribute 'success'
测试失败,提示: 'dict' object has no attribute 'success'
❌ WRONG:
mock_service.get_data = AsyncMock(return_value={"items": []})
✅ CORRECT:
from project_watch_mcp.domain.common import ServiceResult
mock_service.get_data = AsyncMock(return_value=ServiceResult.ok({"items": []}))
Result: Test passes, ServiceResult pattern enforced
undefined❌ 错误示例:
mock_service.get_data = AsyncMock(return_value={"items": []})
✅ 正确示例:
from project_watch_mcp.domain.common import ServiceResult
mock_service.get_data = AsyncMock(return_value=ServiceResult.ok({"items": []}))
结果: 测试通过,ServiceResult模式规范被严格执行
undefinedTable of Contents
目录
When to Use This Skill
何时使用该技能
Use this skill when seeing:
- Mock errors:
'dict' object has no attribute 'success' - Async errors:
coroutine object has no attribute 'success' - Type errors: with ServiceResult[T]
Incompatible types in assignment - Unwrap errors:
Cannot unwrap None data from successful result - Test failures: Mock assertions failing with ServiceResult
Trigger phrases:
- "Mock not returning ServiceResult"
- "dict object has no attribute success"
- "Fix ServiceResult errors"
- "ServiceResult type errors"
- "Mock configuration incorrect"
当遇到以下情况时使用该技能:
- Mock错误:
'dict' object has no attribute 'success' - 异步错误:
coroutine object has no attribute 'success' - 类型错误: 与ServiceResult[T]相关
Incompatible types in assignment - 解包错误:
Cannot unwrap None data from successful result - 测试失败: 与ServiceResult相关的mock断言失败
触发关键词:
- "Mock未返回ServiceResult"
- "dict object has no attribute success"
- "修复ServiceResult错误"
- "ServiceResult类型错误"
- "Mock配置不正确"
What This Skill Does
该技能能做什么
This skill provides systematic fixes for:
- Mock configuration errors - Fix mocks returning dict instead of ServiceResult
- Async ServiceResult patterns - Configure AsyncMock with proper return_value
- ServiceResult chaining - Use composition utilities (map, bind, flatmap)
- Type error resolution - Fix ServiceResult[T] type mismatches
- Unwrap safety - Handle None data and failure cases correctly
See Instructions section below for detailed diagnostic workflow.
该技能提供以下问题的系统化修复方案:
- Mock配置错误 - 修复返回dict而非ServiceResult的mock
- 异步ServiceResult模式 - 为AsyncMock配置正确的return_value
- ServiceResult链式调用 - 使用组合工具(map、bind、flatmap)
- 类型错误解决 - 修复ServiceResult[T]类型不匹配问题
- 安全解包 - 正确处理None数据和失败场景
详细诊断流程请见下方的操作步骤部分。
Instructions
操作步骤
Step 1: Identify the Error Pattern
步骤1:识别错误模式
Run the test and classify the error:
bash
uv run pytest tests/path/to/failing_test.py -vCommon Error Signatures:
-
Mock Returns Dict
- Error:
'dict' object has no attribute 'success' - Cause: Mock configured with
return_value = {"key": "value"} - Fix: Use
return_value = ServiceResult.ok({"key": "value"})
- Error:
-
Async Mock Missing Await
- Error:
coroutine object has no attribute 'success' - Cause: AsyncMock returns coroutine, not ServiceResult
- Fix: Use
AsyncMock(return_value=ServiceResult.ok(...))
- Error:
-
Type Error with Chaining
- Error:
Incompatible types in assignment - Cause: ServiceResult[T] type mismatch in chained operations
- Fix: Use proper type annotations and composition utilities
- Error:
-
Unwrap on None Data
- Error:
Cannot unwrap None data from successful result - Cause:
ServiceResult.ok(None).unwrap() - Fix: Check before unwrapping
result.data is not None
- Error:
运行测试并对错误分类:
bash
uv run pytest tests/path/to/failing_test.py -v常见错误特征:
-
Mock返回Dict
- 错误信息:
'dict' object has no attribute 'success' - 原因: Mock被配置为
return_value = {"key": "value"} - 修复: 使用
return_value = ServiceResult.ok({"key": "value"})
- 错误信息:
-
异步Mock缺少正确返回值
- 错误信息:
coroutine object has no attribute 'success' - 原因: AsyncMock返回协程而非ServiceResult
- 修复: 使用
AsyncMock(return_value=ServiceResult.ok(...))
- 错误信息:
-
链式调用中的类型错误
- 错误信息:
Incompatible types in assignment - 原因: 链式操作中ServiceResult[T]类型不匹配
- 修复: 使用正确的类型注解和组合工具
- 错误信息:
-
对None数据解包
- 错误信息:
Cannot unwrap None data from successful result - 原因:
ServiceResult.ok(None).unwrap() - 修复: 解包前检查
result.data is not None
- 错误信息:
Step 2: Fix Mock Configuration
步骤2:修复Mock配置
❌ WRONG - Mock Returns Dict:
python
mock_service.get_data = AsyncMock(return_value={"items": []})❌ 错误示例 - Mock返回Dict:
python
mock_service.get_data = AsyncMock(return_value={"items": []})Causes: 'dict' object has no attribute 'success'
导致错误: 'dict' object has no attribute 'success'
**✅ CORRECT - Mock Returns ServiceResult:**
```python
from project_watch_mcp.domain.common import ServiceResult
mock_service.get_data = AsyncMock(
return_value=ServiceResult.ok({"items": []})
)Pattern for Multiple Mock Methods:
Use MultiEdit to fix all mocks in one operation:
python
undefined
**✅ 正确示例 - Mock返回ServiceResult:**
```python
from project_watch_mcp.domain.common import ServiceResult
mock_service.get_data = AsyncMock(
return_value=ServiceResult.ok({"items": []})
)多Mock方法修复模式:
使用批量编辑一次修复所有mock:
python
undefinedFix all mocks in test file at once
一次性修复测试文件中的所有mock
mock_repo.file_exists = AsyncMock(return_value=ServiceResult.ok(False))
mock_repo.store_file = AsyncMock(return_value=ServiceResult.ok())
mock_service.create_chunks = AsyncMock(return_value=ServiceResult.ok(chunks))
undefinedmock_repo.file_exists = AsyncMock(return_value=ServiceResult.ok(False))
mock_repo.store_file = AsyncMock(return_value=ServiceResult.ok())
mock_service.create_chunks = AsyncMock(return_value=ServiceResult.ok(chunks))
undefinedStep 3: Fix ServiceResult Chaining
步骤3:修复ServiceResult链式调用
Common Chaining Mistakes:
-
Direct Data Access Without Checkpython
# ❌ WRONG - No success check result = service.get_data() data = result.data # Could be None on failure! # ✅ CORRECT - Check success first result = service.get_data() if result.success: data = result.data else: return ServiceResult.fail(result.error) -
Sequential Operationspython
# ❌ WRONG - Manual chaining result1 = service1.operation() if result1.success: result2 = service2.operation(result1.data) if result2.success: return result2 return result1 if not result1.success else result2 # ✅ CORRECT - Use composition utilities from project_watch_mcp.domain.common.service_result_utils import compose_results result = service1.operation() result = compose_results(lambda d: service2.operation(d), result) return result -
Async Contextpython
# ✅ CORRECT - Async ServiceResult pattern async def process_file(file_path: Path) -> ServiceResult[dict]: result = await self.reader.read_file(file_path) if result.is_failure: return ServiceResult.fail(result.error) # result.success guarantees result.data is not None content = result.data return ServiceResult.ok({"content": content})
常见链式调用错误:
-
未检查状态直接访问数据python
# ❌ 错误示例 - 未检查成功状态 result = service.get_data() data = result.data # 失败时可能为None! # ✅ 正确示例 - 先检查成功状态 result = service.get_data() if result.success: data = result.data else: return ServiceResult.fail(result.error) -
顺序操作python
# ❌ 错误示例 - 手动链式调用 result1 = service1.operation() if result1.success: result2 = service2.operation(result1.data) if result2.success: return result2 return result1 if not result1.success else result2 # ✅ 正确示例 - 使用组合工具 from project_watch_mcp.domain.common.service_result_utils import compose_results result = service1.operation() result = compose_results(lambda d: service2.operation(d), result) return result -
异步上下文python
# ✅ 正确示例 - 异步ServiceResult模式 async def process_file(file_path: Path) -> ServiceResult[dict]: result = await self.reader.read_file(file_path) if result.is_failure: return ServiceResult.fail(result.error) # result.success保证result.data不为None content = result.data return ServiceResult.ok({"content": content})
Step 4: Use ServiceResult Composition Utilities
步骤4:使用ServiceResult组合工具
Import composition utilities for complex workflows:
python
from project_watch_mcp.domain.common.service_result_utils import (
compose_results, # Monadic bind (flatMap)
map_result, # Functor map
chain_results, # Chain multiple results
collect_results, # Collect list of results
flatten_results, # Flatten nested results
unwrap_or_fail, # Convert to exception
)Examples:
python
undefined导入组合工具处理复杂流程:
python
from project_watch_mcp.domain.common.service_result_utils import (
compose_results, # 单子绑定(flatMap)
map_result, # 函子映射
chain_results, # 链式多个结果
collect_results, # 收集结果列表
flatten_results, # 展平嵌套结果
unwrap_or_fail, # 转换为异常
)示例:
python
undefinedMap over successful result
对成功结果进行映射
result = ServiceResult.ok([1, 2, 3])
doubled = map_result(lambda items: [x * 2 for x in items], result)
result = ServiceResult.ok([1, 2, 3])
doubled = map_result(lambda items: [x * 2 for x in items], result)
Result: ServiceResult.ok([2, 4, 6])
结果: ServiceResult.ok([2, 4, 6])
Compose operations (flatMap)
组合操作(flatMap)
def validate(data: dict) -> ServiceResult[dict]:
if "required_field" in data:
return ServiceResult.ok(data)
return ServiceResult.fail("Missing required field")
result = ServiceResult.ok({"required_field": "value"})
validated = compose_results(validate, result)
def validate(data: dict) -> ServiceResult[dict]:
if "required_field" in data:
return ServiceResult.ok(data)
return ServiceResult.fail("Missing required field")
result = ServiceResult.ok({"required_field": "value"})
validated = compose_results(validate, result)
Chain multiple results
链式多个结果
result1 = ServiceResult.ok(10)
result2 = ServiceResult.ok(20)
result3 = ServiceResult.ok(30)
combined = chain_results(result1, result2, result3)
result1 = ServiceResult.ok(10)
result2 = ServiceResult.ok(20)
result3 = ServiceResult.ok(30)
combined = chain_results(result1, result2, result3)
Result: ServiceResult.ok([10, 20, 30])
结果: ServiceResult.ok([10, 20, 30])
undefinedundefinedStep 5: Fix Type Errors
步骤5:修复类型错误
Common Type Issues:
-
Generic Type Mismatchpython
# ❌ WRONG - Type mismatch def process() -> ServiceResult[list[str]]: result: ServiceResult[dict] = get_data() return result # Type error! # ✅ CORRECT - Proper type transformation def process() -> ServiceResult[list[str]]: result: ServiceResult[dict] = get_data() if result.is_failure: return ServiceResult.fail(result.error) items = list(result.data.keys()) return ServiceResult.ok(items) -
Optional Data Handlingpython
# ❌ WRONG - Not handling None result = ServiceResult.ok(None) value = result.unwrap() # Raises ValueError! # ✅ CORRECT - Use unwrap_or for optional data result = ServiceResult.ok(None) value = result.unwrap_or([]) # Returns default on None/failure
常见类型问题:
-
泛型类型不匹配python
# ❌ 错误示例 - 类型不匹配 def process() -> ServiceResult[list[str]]: result: ServiceResult[dict] = get_data() return result # 类型错误! # ✅ 正确示例 - 正确的类型转换 def process() -> ServiceResult[list[str]]: result: ServiceResult[dict] = get_data() if result.is_failure: return ServiceResult.fail(result.error) items = list(result.data.keys()) return ServiceResult.ok(items) -
可选数据处理python
# ❌ 错误示例 - 未处理None result = ServiceResult.ok(None) value = result.unwrap() # 抛出ValueError! # ✅ 正确示例 - 对可选数据使用unwrap_or result = ServiceResult.ok(None) value = result.unwrap_or([]) # None/失败时返回默认值
Step 6: Validate Fix
步骤6:验证修复
After fixing mocks and ServiceResult usage:
bash
undefined修复mock和ServiceResult使用方式后:
bash
undefinedRun the specific test
运行指定测试
uv run pytest tests/path/to/test_file.py::test_name -v
uv run pytest tests/path/to/test_file.py::test_name -v
Run all related tests
运行所有相关测试
uv run pytest tests/unit/application/ -v -k "service"
uv run pytest tests/unit/application/ -v -k "service"
Verify type safety
验证类型安全
uv run pyright src/project_watch_mcp/
undefineduv run pyright src/project_watch_mcp/
undefinedUsage Examples
使用示例
Example 1: Fix Mock Returns Dict Error
示例1:修复Mock返回Dict错误
Scenario: Test fails with
'dict' object has no attribute 'success'Before (Failing Test):
python
@pytest.fixture
def mock_repository():
repo = MagicMock(spec=CodeRepository)
# ❌ WRONG - Returns dict, not ServiceResult
repo.get_files = AsyncMock(return_value={"files": []})
return repo
async def test_get_files(mock_repository):
handler = FileHandler(mock_repository)
result = await handler.process()
# Fails: 'dict' object has no attribute 'success'
assert result.success is TrueAfter (Fixed Test):
python
from project_watch_mcp.domain.common import ServiceResult
@pytest.fixture
def mock_repository():
repo = MagicMock(spec=CodeRepository)
# ✅ CORRECT - Returns ServiceResult
repo.get_files = AsyncMock(
return_value=ServiceResult.ok({"files": []})
)
return repo
async def test_get_files(mock_repository):
handler = FileHandler(mock_repository)
result = await handler.process()
# Now works correctly
assert result.success is True
assert result.data == {"files": []}场景: 测试失败,提示
'dict' object has no attribute 'success'修复前(测试失败):
python
@pytest.fixture
def mock_repository():
repo = MagicMock(spec=CodeRepository)
# ❌ 错误示例 - 返回dict而非ServiceResult
repo.get_files = AsyncMock(return_value={"files": []})
return repo
async def test_get_files(mock_repository):
handler = FileHandler(mock_repository)
result = await handler.process()
# 失败: 'dict' object has no attribute 'success'
assert result.success is True修复后(测试通过):
python
from project_watch_mcp.domain.common import ServiceResult
@pytest.fixture
def mock_repository():
repo = MagicMock(spec=CodeRepository)
# ✅ 正确示例 - 返回ServiceResult
repo.get_files = AsyncMock(
return_value=ServiceResult.ok({"files": []})
)
return repo
async def test_get_files(mock_repository):
handler = FileHandler(mock_repository)
result = await handler.process()
# 现在正常工作
assert result.success is True
assert result.data == {"files": []}Example 2: Fix Async ServiceResult Pattern
示例2:修复异步ServiceResult模式
Scenario: Async mock returning coroutine instead of ServiceResult
Fix:
python
from project_watch_mcp.domain.common import ServiceResult场景: 异步mock返回协程而非ServiceResult
修复:
python
from project_watch_mcp.domain.common import ServiceResult❌ WRONG - AsyncMock without proper return_value
❌ 错误示例 - AsyncMock未配置正确的return_value
service.embed_text = AsyncMock()
service.embed_text = AsyncMock()
✅ CORRECT - AsyncMock with ServiceResult return_value
✅ 正确示例 - AsyncMock配置ServiceResult返回值
service.embed_text = AsyncMock(
return_value=ServiceResult.ok([0.1, 0.2, 0.3])
)
For more examples, see **[references/troubleshooting.md](./references/troubleshooting.md)** and **[templates/serviceresult-patterns.md](./templates/serviceresult-patterns.md)**.service.embed_text = AsyncMock(
return_value=ServiceResult.ok([0.1, 0.2, 0.3])
)
更多示例,请查看 **[references/troubleshooting.md](./references/troubleshooting.md)** 和 **[templates/serviceresult-patterns.md](./templates/serviceresult-patterns.md)**。Expected Outcomes
预期结果
Successful Fix:
- Test passes after mock returns ServiceResult
- AsyncMock configured with proper return_value
- Type annotations match ServiceResult[T]
- No pyright errors
- Unwrap safety checks in place
Refactoring Opportunity Identified:
- Sequential checks detected
if result.success: - Recommendation: Use compose_results() utilities
- See Step 4 in Instructions for composition utilities
修复成功:
- Mock返回ServiceResult后测试通过
- AsyncMock配置了正确的return_value
- 类型注解与ServiceResult[T]匹配
- 无pyright错误
- 已添加解包安全检查
识别到重构机会:
- 检测到顺序检查
if result.success: - 建议: 使用compose_results()工具
- 请查看操作步骤的步骤4了解组合工具详情
Requirements
要求
Imports:
from project_watch_mcp.domain.common import ServiceResultfrom project_watch_mcp.domain.common.service_result_utils import <utility>- (for async methods)
from unittest.mock import AsyncMock
Tools:
- Read - View test files and service implementations
- Edit/MultiEdit - Fix mock configurations and ServiceResult usage
- Grep - Find all occurrences of pattern
- Glob - Locate test files with ServiceResult issues
Knowledge:
- ServiceResult pattern (success/failure monad)
- AsyncMock vs MagicMock differences
- Python type annotations (ServiceResult[T])
- Composition utilities (map, bind, flatmap)
Optional:
- Understanding of monad pattern
- Familiarity with functional programming concepts
导入依赖:
from project_watch_mcp.domain.common import ServiceResultfrom project_watch_mcp.domain.common.service_result_utils import <utility>- (用于异步方法)
from unittest.mock import AsyncMock
工具:
- 阅读 - 查看测试文件和服务实现
- 编辑/批量编辑 - 修复mock配置和ServiceResult使用方式
- Grep - 查找所有模式出现的位置
- Glob - 定位存在ServiceResult问题的测试文件
知识储备:
- ServiceResult模式(成功/失败单子)
- AsyncMock与MagicMock的区别
- Python类型注解(ServiceResult[T])
- 组合工具(map、bind、flatmap)
可选:
- 单子模式理解
- 函数式编程概念 familiarity
Troubleshooting
故障排除
For detailed troubleshooting steps and validation workflows, see references/troubleshooting.md.
Quick fixes:
- → Use
'dict' object has no attribute 'success'instead ofServiceResult.ok(data)data - → Add
coroutine object has no attribute 'success'to AsyncMockreturn_value - Type errors → Check ServiceResult[T] generic type matches
- Unwrap errors → Use for optional data
unwrap_or(default)
详细的故障排除步骤和验证流程,请查看 references/troubleshooting.md。
快速修复:
- → 使用
'dict' object has no attribute 'success'替代ServiceResult.ok(data)data - → 为AsyncMock添加
coroutine object has no attribute 'success'return_value - 类型错误 → 检查ServiceResult[T]泛型类型是否匹配
- 解包错误 → 对可选数据使用
unwrap_or(default)
Red Flags to Avoid
需避免的警示信号
-
Forgetting ServiceResult Wrapper
- ❌
return_value = data - ✅
return_value = ServiceResult.ok(data)
- ❌
-
Not Checking Success Before Data Access
- ❌
data = result.data - ✅
if result.success: data = result.data
- ❌
-
Using unwrap() Without Null Check
- ❌ (raises on None)
value = result.unwrap() - ✅
value = result.unwrap_or(default)
- ❌
-
Mixing Async and Sync Mocks
- ❌ for async method
MagicMock(return_value=ServiceResult.ok(...)) - ✅ for async method
AsyncMock(return_value=ServiceResult.ok(...))
- ❌
-
Not Propagating Errors
- ❌ Silently ignoring failure results
- ✅ Returning failure immediately:
if result.is_failure: return result
-
忘记ServiceResult包装
- ❌
return_value = data - ✅
return_value = ServiceResult.ok(data)
- ❌
-
未检查成功状态直接访问数据
- ❌
data = result.data - ✅
if result.success: data = result.data
- ❌
-
未做空值检查使用unwrap()
- ❌ (None时抛出异常)
value = result.unwrap() - ✅
value = result.unwrap_or(default)
- ❌
-
混合异步和同步Mock
- ❌ 异步方法使用
MagicMock(return_value=ServiceResult.ok(...)) - ✅ 异步方法使用
AsyncMock(return_value=ServiceResult.ok(...))
- ❌ 异步方法使用
-
未传播错误
- ❌ 静默忽略失败结果
- ✅ 立即返回失败结果:
if result.is_failure: return result
Automation Scripts
自动化脚本
Powerful automation utilities to detect and fix ServiceResult issues automatically.
强大的自动化工具,可自动检测和修复ServiceResult问题。
Available Scripts
可用脚本
- fix_serviceresult_mocks.py - Auto-fix test mock errors
- validate_serviceresult_usage.py - Validate ServiceResult patterns
- find_serviceresult_chains.py - Identify refactoring opportunities
Usage:
bash
undefined- fix_serviceresult_mocks.py - 自动修复测试mock错误
- validate_serviceresult_usage.py - 验证ServiceResult模式
- find_serviceresult_chains.py - 识别重构机会
使用方式:
bash
undefinedFix all test mocks automatically
自动修复所有测试mock
python scripts/fix_serviceresult_mocks.py --all tests/
python scripts/fix_serviceresult_mocks.py --all tests/
Find all violations in codebase
查找代码库中的所有违规情况
python scripts/validate_serviceresult_usage.py src/
python scripts/validate_serviceresult_usage.py src/
Get refactoring suggestions
获取重构建议
python scripts/find_serviceresult_chains.py --suggest-refactor src/
---python scripts/find_serviceresult_chains.py --suggest-refactor src/
---See Also
另请参阅
Supporting Files
支持文件
- references/troubleshooting.md - Detailed troubleshooting guide with validation workflows
- references/advanced-patterns.md - Integration points, benefits analysis, and success metrics
- templates/serviceresult-patterns.md - Quick reference templates
- references/monad-pattern.md - Understanding the monad pattern
- references/troubleshooting.md - 包含验证流程的详细故障排除指南
- references/advanced-patterns.md - 集成点、收益分析和成功指标
- templates/serviceresult-patterns.md - 快速参考模板
- references/monad-pattern.md - 单子模式详解
Related Skills
相关技能
- test-debug-failures - Fix ServiceResult-specific test failures
- python-best-practices-type-safety - Resolve ServiceResult[T] type mismatches
- test-setup-async - Configure AsyncMock with ServiceResult
- implement-cqrs-handler - Ensure handlers return ServiceResult
- implement-repository-pattern - Validate repository ServiceResult returns
- test-debug-failures - 修复ServiceResult相关的测试失败
- python-best-practices-type-safety - 解决ServiceResult[T]类型不匹配问题
- test-setup-async - 为AsyncMock配置ServiceResult
- implement-cqrs-handler - 确保处理器返回ServiceResult
- implement-repository-pattern - 验证仓库的ServiceResult返回值