Files
DjangoAdmin_Flask_EleVue/tests/unit/test_modules/test_position_service.py
T
DjangoAdmin DevandClaude 0cfaf8c894 refactor: P4b position 标杆模块服务层改造 + 单元测试
【服务层新范式】system/position 作为标杆:
- service 函数改「入参数据/出参数据」:get_position_page(params)->dict、
  add_position(data)/update_position(data)/update_position_status(data)->None、
  delete_positions(ids)->int
- 业务失败 raise BizError(不再 return R.failed),由全局处理器转 R.failed
- get_info 委托 PositionRepository(新增 repository.py,继承 BaseRepository)
- router 负责取参(query args / parse_request_body)与 R 包装

【单元测试】tests/unit/test_modules/test_position_service.py:
- 纯函数(_build_page_data)、BizError 契约(空数据/空ID/无效ID)、
  mock 批量删除(ID 解析验证)——无需数据库即可测试
- conftest flask_app fixture 增加 SECRET_KEY + 关闭 CSRF

【验收】12 passed(5 响应 + 7 position);应用启动;flake8 零告警;
position 路由 401 拦截正常。服务层测试化范式验证可行

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-07 14:42:03 +08:00

82 lines
2.5 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.
"""
岗位服务单元测试(P4 服务层改造标杆)
=============================================================
验证 P4 改造后的服务层契约:
- 服务函数「入参数据、出参数据」
- 业务失败通过 raise BizError 表达(不再 return R.failed)
- 纯函数与可 mock 路径无需数据库即可测试
"""
import pytest
from src.core.exceptions import BizError
from src.modules.system.position import service as position_service
class TestBuildPageData:
"""分页数据构建(纯函数)"""
def test_shape(self):
data = position_service._build_page_data([], 0, 10, 1, 0)
assert data == {'records': [], 'total': 0, 'size': 10, 'current': 1, 'pages': 0}
class TestAddPosition:
"""添加岗位"""
def test_empty_data_raises_bizerror(self, flask_app):
"""空数据触发表单验证失败 → BizError(FlaskForm 需应用上下文)"""
with flask_app.app_context():
with pytest.raises(BizError):
position_service.add_position({})
class TestUpdatePosition:
"""更新岗位"""
def test_empty_data_raises_bizerror(self, flask_app):
with flask_app.app_context():
with pytest.raises(BizError):
position_service.update_position({})
class TestUpdateStatus:
"""状态设置"""
def test_empty_data_raises_bizerror(self, flask_app):
with flask_app.app_context():
with pytest.raises(BizError):
position_service.update_position_status({})
class TestDeletePositions:
"""批量删除"""
def test_empty_raises(self):
"""空 ID 触发 BizError"""
with pytest.raises(BizError, match="记录ID不存在"):
position_service.delete_positions('')
def test_invalid_ids_raises(self):
"""非数字 ID 解析为空 → BizError"""
with pytest.raises(BizError, match="无效的记录ID"):
position_service.delete_positions('abc')
def test_parse_and_delete(self, monkeypatch):
"""ID 解析后调用模型批量删除,返回删除计数"""
from src.modules.system.position.models import Position
captured = {}
def fake_batch_delete(cls, ids):
captured['ids'] = ids
return len(ids)
monkeypatch.setattr(Position, 'batch_delete', classmethod(fake_batch_delete))
count = position_service.delete_positions('1,2,3')
assert count == 3
assert captured['ids'] == [1, 2, 3]