test_wechat_mp_message.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. from unittest.mock import MagicMock, patch
  2. from app.core.config import settings
  3. def test_send_approval_requires_mp_openid():
  4. from app.services.wechat_mp_message import send_oa_approval_notify
  5. r = send_oa_approval_notify(
  6. mp_openid="",
  7. pagepath="pages/oa/webview/index?instanceId=i1&taskId=t1&mode=approve",
  8. title="请假",
  9. applicant="张三",
  10. node_name="主管审批",
  11. time_text="2026-08-13 12:00",
  12. )
  13. assert r.get("success") is False
  14. assert r.get("error") == "missing_mp_openid"
  15. def test_send_approval_requires_template_id():
  16. from app.services.wechat_mp_message import send_oa_approval_notify
  17. with patch.object(settings, "WX_MP_TEMPLATE_APPROVAL", ""):
  18. r = send_oa_approval_notify(
  19. mp_openid="mp_openid_1",
  20. pagepath="pages/oa/webview/index?instanceId=i1&taskId=t1&mode=approve",
  21. title="请假",
  22. applicant="张三",
  23. node_name="主管审批",
  24. time_text="2026-08-13 12:00",
  25. )
  26. assert r.get("success") is False
  27. assert r.get("error") == "missing_template_id"
  28. @patch("app.services.wechat_mp_message.get_mp_access_token", return_value="tok_mp")
  29. @patch("app.services.wechat_mp_message.httpx.Client")
  30. def test_send_approval_success_payload_shape(mock_client_cls, _mock_token):
  31. from app.services.wechat_mp_message import send_oa_approval_notify
  32. mock_resp = MagicMock()
  33. mock_resp.raise_for_status = MagicMock()
  34. mock_resp.json.return_value = {"errcode": 0, "msgid": 1001}
  35. mock_client = MagicMock()
  36. mock_client.__enter__.return_value = mock_client
  37. mock_client.__exit__.return_value = False
  38. mock_client.post.return_value = mock_resp
  39. mock_client_cls.return_value = mock_client
  40. long_title = "这是一个非常非常长的审批标题需要截断处理一下才行"
  41. with patch.object(settings, "WX_MP_TEMPLATE_APPROVAL", "tpl_approval"), patch.object(
  42. settings, "WXPAY_MINI_APPID", "wx_mini_appid"
  43. ), patch.object(settings, "WX_MP_TPL_FIELD_TITLE", "thing1"), patch.object(
  44. settings, "WX_MP_TPL_FIELD_APPLICANT", "thing2"
  45. ), patch.object(settings, "WX_MP_TPL_FIELD_NODE", "thing3"), patch.object(
  46. settings, "WX_MP_TPL_FIELD_TIME", "time4"
  47. ):
  48. r = send_oa_approval_notify(
  49. mp_openid="mp_openid_1",
  50. pagepath="/pages/oa/webview/index?instanceId=i1&taskId=t1&mode=approve",
  51. title=long_title,
  52. applicant="张三",
  53. node_name="主管审批",
  54. time_text="2026-08-13 12:00",
  55. )
  56. assert r == {"success": True, "msgid": 1001}
  57. assert mock_client.post.call_count == 1
  58. args, kwargs = mock_client.post.call_args
  59. assert args[0].startswith(
  60. "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="
  61. )
  62. payload = kwargs["json"]
  63. assert payload["touser"] == "mp_openid_1"
  64. assert payload["template_id"] == "tpl_approval"
  65. assert payload["miniprogram"] == {
  66. "appid": "wx_mini_appid",
  67. "pagepath": "pages/oa/webview/index?instanceId=i1&taskId=t1&mode=approve",
  68. }
  69. assert payload["data"]["thing1"]["value"] == long_title[:20]
  70. assert payload["data"]["thing2"]["value"] == "张三"
  71. assert payload["data"]["thing3"]["value"] == "主管审批"
  72. assert payload["data"]["time4"]["value"] == "2026-08-13 12:00"
  73. @patch("app.services.wechat_mp_message.get_mp_access_token", return_value="tok_mp")
  74. @patch("app.services.wechat_mp_message.httpx.Client")
  75. def test_send_cc_success_payload_shape(mock_client_cls, _mock_token):
  76. from app.services.wechat_mp_message import send_oa_cc_notify
  77. mock_resp = MagicMock()
  78. mock_resp.raise_for_status = MagicMock()
  79. mock_resp.json.return_value = {"errcode": 0, "msgid": 2002}
  80. mock_client = MagicMock()
  81. mock_client.__enter__.return_value = mock_client
  82. mock_client.__exit__.return_value = False
  83. mock_client.post.return_value = mock_resp
  84. mock_client_cls.return_value = mock_client
  85. with patch.object(settings, "WX_MP_TEMPLATE_CC", "tpl_cc"), patch.object(
  86. settings, "WXPAY_MINI_APPID", "wx_mini_appid"
  87. ):
  88. r = send_oa_cc_notify(
  89. mp_openid="mp_openid_2",
  90. pagepath="pages/oa/webview/index?instanceId=i2&taskId=t2&mode=view",
  91. title="报销",
  92. applicant="李四",
  93. node_name="抄送知会",
  94. time_text="2026-08-13 15:30",
  95. )
  96. assert r == {"success": True, "msgid": 2002}
  97. payload = mock_client.post.call_args.kwargs["json"]
  98. assert payload["touser"] == "mp_openid_2"
  99. assert payload["template_id"] == "tpl_cc"
  100. assert payload["miniprogram"]["appid"] == "wx_mini_appid"
  101. assert payload["miniprogram"]["pagepath"].endswith("mode=view")
  102. assert "thing1" in payload["data"]
  103. assert payload["data"]["thing1"]["value"] == "报销"