test_mp_bind.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. """服务号 mp-bind / mp-bind-status:成功与冲突路径(mock oauth)。"""
  2. from types import SimpleNamespace
  3. from unittest.mock import AsyncMock, MagicMock, patch
  4. import pytest
  5. from fastapi import HTTPException
  6. @pytest.mark.asyncio
  7. async def test_mp_bind_success():
  8. user = SimpleNamespace(
  9. id="u1",
  10. del_flag=0,
  11. wx_mp_openid=None,
  12. wx_unionid=None,
  13. wx_mp_bind_time=None,
  14. update_time=None,
  15. )
  16. db = MagicMock()
  17. with (
  18. patch(
  19. "app.api.mini_auth._resolve_user_id",
  20. new_callable=AsyncMock,
  21. return_value="u1",
  22. ),
  23. patch(
  24. "app.api.mini_auth.oauth_code_to_openid",
  25. return_value={"openid": "mp-oid-1", "unionid": "uni-1"},
  26. ),
  27. patch("app.api.mini_auth.user_crud.get_by_wx_mp_openid", return_value=None),
  28. patch("app.api.mini_auth.user_crud.get", return_value=user),
  29. ):
  30. from app.api.mini_auth import mp_bind
  31. resp = await mp_bind(
  32. request=MagicMock(),
  33. body={"code": "oauth-code"},
  34. db=db,
  35. )
  36. assert resp["code"] == 200
  37. assert resp["data"]["bound"] is True
  38. assert user.wx_mp_openid == "mp-oid-1"
  39. assert user.wx_unionid == "uni-1"
  40. assert user.wx_mp_bind_time is not None
  41. db.add.assert_called_once_with(user)
  42. db.commit.assert_called_once()
  43. @pytest.mark.asyncio
  44. async def test_mp_bind_conflict_when_openid_bound_to_other():
  45. other = SimpleNamespace(id="u-other")
  46. db = MagicMock()
  47. with (
  48. patch(
  49. "app.api.mini_auth._resolve_user_id",
  50. new_callable=AsyncMock,
  51. return_value="u1",
  52. ),
  53. patch(
  54. "app.api.mini_auth.oauth_code_to_openid",
  55. return_value={"openid": "mp-oid-taken", "unionid": None},
  56. ),
  57. patch(
  58. "app.api.mini_auth.user_crud.get_by_wx_mp_openid",
  59. return_value=other,
  60. ),
  61. ):
  62. from app.api.mini_auth import mp_bind
  63. resp = await mp_bind(
  64. request=MagicMock(),
  65. body={"code": "oauth-code"},
  66. db=db,
  67. )
  68. assert resp["code"] == 409
  69. assert "已绑定其他账号" in resp["message"]
  70. db.commit.assert_not_called()
  71. @pytest.mark.asyncio
  72. async def test_mp_bind_status_bound_true():
  73. user = SimpleNamespace(id="u1", wx_mp_openid="mp-oid-1")
  74. with (
  75. patch(
  76. "app.api.mini_auth._resolve_user_id",
  77. new_callable=AsyncMock,
  78. return_value="u1",
  79. ),
  80. patch("app.api.mini_auth.user_crud.get", return_value=user),
  81. ):
  82. from app.api.mini_auth import mp_bind_status
  83. resp = await mp_bind_status(request=MagicMock(), db=MagicMock())
  84. assert resp["code"] == 200
  85. assert resp["data"]["bound"] is True
  86. @pytest.mark.asyncio
  87. async def test_mp_bind_unauthorized():
  88. with patch(
  89. "app.api.mini_auth._resolve_user_id",
  90. new_callable=AsyncMock,
  91. side_effect=HTTPException(status_code=401, detail="未授权"),
  92. ):
  93. from app.api.mini_auth import mp_bind
  94. resp = await mp_bind(
  95. request=MagicMock(),
  96. body={"code": "x"},
  97. db=MagicMock(),
  98. )
  99. assert resp["code"] == 401
  100. assert resp["message"] == "未授权"