# 微信服务测试套件实现 **日期**: 2026-01-29 **类型**: 测试 **影响范围**: 微信登录服务测试 ## 概述 完成微信登录服务的完整测试套件,包括单元测试和集成测试,覆盖所有核心功能。 ## 测试文件 ### 1. 单元测试 **文件**: `server/tests/unit/test_wechat_service.py` #### 测试覆盖 ##### TestGenerateQrcode - 生成二维码测试 - ✅ `test_generate_qrcode_mp_platform` - 测试生成公众号二维码 - ✅ `test_generate_qrcode_open_platform` - 测试生成开放平台二维码 - ✅ `test_generate_qrcode_invalid_platform` - 测试无效平台类型 ##### TestHandleCallback - 处理回调测试 - ✅ `test_handle_callback_success` - 测试成功处理回调 - ✅ `test_handle_callback_invalid_platform` - 测试无效平台 ##### TestGetLoginResult - 获取登录结果测试 - ✅ `test_get_login_result_pending` - 测试等待中状态 - ✅ `test_get_login_result_new_user` - 测试新用户自动注册 - ✅ `test_get_login_result_existing_user` - 测试已存在用户登录 ##### TestBindWechat - 绑定微信测试 - ✅ `test_bind_wechat_success` - 测试成功绑定 - ✅ `test_bind_wechat_already_bound` - 测试微信已被其他用户绑定 ##### TestUnbindWechat - 解绑微信测试 - ✅ `test_unbind_wechat_success` - 测试成功解绑 - ✅ `test_unbind_wechat_user_not_found` - 测试用户不存在 ### 2. 集成测试 **文件**: `server/tests/integration/test_wechat_api.py` #### 测试覆盖 ##### TestWechatQrcodeAPI - 二维码 API 测试 - `test_get_qrcode_mp_platform` - 测试获取公众号二维码 - `test_get_qrcode_open_platform` - 测试获取开放平台二维码 - `test_get_qrcode_invalid_platform` - 测试无效平台 ##### TestWechatLoginResultAPI - 登录结果 API 测试 - `test_get_login_result_pending` - 测试等待中状态 - `test_get_login_result_success` - 测试登录成功 ##### TestWechatBindAPI - 绑定 API 测试 - `test_bind_wechat_success` - 测试成功绑定 - `test_bind_wechat_unauthorized` - 测试未认证 - `test_bind_wechat_invalid_platform` - 测试无效平台 ##### TestWechatUnbindAPI - 解绑 API 测试 - `test_unbind_wechat_success` - 测试成功解绑 - `test_unbind_wechat_unauthorized` - 测试未认证 ##### TestWechatCallbackAPI - 回调 API 测试 - `test_callback_success` - 测试成功处理回调 - `test_callback_error` - 测试回调错误 ## 测试执行结果 ### 单元测试 ```bash $ docker exec jointo-server-app pytest tests/unit/test_wechat_service.py -v ============================= test session starts ============================== platform linux -- Python 3.12.12, pytest-7.4.4, pluggy-1.6.0 cachedir: .pytest_cache rootdir: /app configfile: pytest.ini plugins: cov-4.1.0, asyncio-0.23.3, anyio-4.12.1 asyncio: mode=Mode.AUTO collecting ... collected 12 items tests/unit/test_wechat_service.py::TestGenerateQrcode::test_generate_qrcode_mp_platform PASSED [ 8%] tests/unit/test_wechat_service.py::TestGenerateQrcode::test_generate_qrcode_open_platform PASSED [ 16%] tests/unit/test_wechat_service.py::TestGenerateQrcode::test_generate_qrcode_invalid_platform PASSED [ 25%] tests/unit/test_wechat_service.py::TestHandleCallback::test_handle_callback_success PASSED [ 33%] tests/unit/test_wechat_service.py::TestHandleCallback::test_handle_callback_invalid_platform PASSED [ 41%] tests/unit/test_wechat_service.py::TestGetLoginResult::test_get_login_result_pending PASSED [ 50%] tests/unit/test_wechat_service.py::TestGetLoginResult::test_get_login_result_new_user PASSED [ 58%] tests/unit/test_wechat_service.py::TestGetLoginResult::test_get_login_result_existing_user PASSED [ 66%] tests/unit/test_wechat_service.py::TestBindWechat::test_bind_wechat_success PASSED [ 75%] tests/unit/test_wechat_service.py::TestBindWechat::test_bind_wechat_already_bound PASSED [ 83%] tests/unit/test_wechat_service.py::TestUnbindWechat::test_unbind_wechat_success PASSED [ 91%] tests/unit/test_wechat_service.py::TestUnbindWechat::test_unbind_wechat_user_not_found PASSED [100%] ============================== 12 passed in 0.22s =============================== ``` **结果**: ✅ 12/12 测试通过 ## 测试技术要点 ### 1. Mock 策略 #### 数据库会话 Mock ```python @pytest.fixture def mock_session(): session = AsyncMock() session.begin = MagicMock() session.begin.return_value.__aenter__ = AsyncMock() session.begin.return_value.__aexit__ = AsyncMock() return session ``` #### Redis Mock ```python @pytest.fixture def mock_redis(): redis = AsyncMock() return redis ``` #### ThreadPoolExecutor Mock ```python @pytest.fixture def mock_executor(): from concurrent.futures import ThreadPoolExecutor, Future executor = MagicMock(spec=ThreadPoolExecutor) def mock_submit(fn, *args, **kwargs): future = Future() try: result = fn(*args, **kwargs) future.set_result(result) except Exception as e: future.set_exception(e) return future executor.submit = mock_submit return executor ``` ### 2. 异步测试 所有测试使用 `@pytest.mark.asyncio` 装饰器: ```python @pytest.mark.asyncio async def test_generate_qrcode_mp_platform(self, wechat_service, mock_redis): # 测试逻辑 pass ``` ### 3. Patch 策略 使用 `patch.object` 模拟同步方法: ```python with patch.object(wechat_service, '_fetch_wechat_user_info', return_value=mock_user_info): result = await wechat_service.bind_wechat(user_id, 'test_code', 'mp') ``` ### 4. 异常测试 使用 `pytest.raises` 验证异常: ```python with pytest.raises(ValidationError, match="无效的平台类型"): await wechat_service.generate_qrcode(platform='invalid') ``` ## 修复的问题 ### 1. DatabaseError 异常缺失 **问题**: `app.core.exceptions` 缺少 `DatabaseError` 异常类 **修复**: 添加 `DatabaseError` 异常类 ```python class DatabaseError(Exception): """数据库操作异常""" pass ``` **文件**: `server/app/core/exceptions.py` ### 2. ThreadPoolExecutor Mock **问题**: 简单的 `MagicMock()` 无法正确模拟 `ThreadPoolExecutor` **修复**: 使用 `concurrent.futures.Future` 正确模拟 executor ## 测试覆盖率 ### 功能覆盖 - ✅ 生成二维码(公众号/开放平台) - ✅ 处理微信回调 - ✅ 轮询登录结果 - ✅ 新用户自动注册 - ✅ 已存在用户登录 - ✅ 绑定微信账号 - ✅ 解绑微信账号 - ✅ 异常处理(无效平台、用户不存在、已绑定等) ### 边界情况 - ✅ 无效平台类型 - ✅ 微信已被其他用户绑定 - ✅ 用户不存在 - ✅ 等待中状态 ## 后续任务 1. **集成测试执行**: - 需要配置测试环境(Redis、数据库) - 需要 mock 微信 API 调用 - 需要配置认证 fixture 2. **测试覆盖率报告**: ```bash docker exec jointo-server-app pytest tests/unit/test_wechat_service.py --cov=app.services.wechat_service --cov-report=html ``` 3. **端到端测试**: - 完整的微信登录流程测试 - 前端集成测试 ## 参考文档 - [微信服务设计文档](../../requirements/backend/04-services/user/wechat-service.md) - [微信服务实现文档](./2026-01-29-wechat-service-complete-implementation.md) - [Python 测试最佳实践](https://docs.pytest.org/en/stable/contents.html) ## 版本信息 - **测试框架**: pytest 7.4.4 - **异步支持**: pytest-asyncio 0.23.3 - **实现日期**: 2026-01-29 - **测试状态**: ✅ 12/12 通过