diff --git a/server/test/reminder.test.js b/server/test/reminder.test.js index 8b99163..85cbb70 100644 --- a/server/test/reminder.test.js +++ b/server/test/reminder.test.js @@ -82,10 +82,11 @@ test('遇到 43101 立即归零并中止本用户剩余发送', async () => { resetLogs() quota.grant('uD', 9) let called = 0 + const WX_ERROR_MESSAGE = '发送订阅消息失败' const restore = wx.sendSubscribeMessage wx.sendSubscribeMessage = async () => { called++ - const e = new Error('发送订阅消息失败') + const e = new Error(WX_ERROR_MESSAGE) e.errcode = 43101 throw e } @@ -101,6 +102,19 @@ test('遇到 43101 立即归零并中止本用户剩余发送', async () => { assert.strictEqual(called, 1, '失败一次就该停,不该继续打请求') assert.strictEqual(quota.getBalance('uD'), 0, '余额应被归零校正') assert.strictEqual(r.skipped, 3, '含失败那条在内全部计为 skipped') + + // D1 是真正打了请求、被微信 43101 拒绝的那一条:error 字段应保留微信原始错误信息, + // 而不是「根本没发请求」时用的兜底文案 'quota_exhausted'。 + const d1Log = db.prepare("SELECT * FROM remind_logs WHERE anniversaryId = 'D1'").get() + assert.ok(d1Log, 'D1 应写入 remind_logs') + assert.strictEqual(d1Log.status, 'skipped') + assert.strictEqual(d1Log.error, WX_ERROR_MESSAGE, 'D1 应记录微信原始错误信息,而不是 quota_exhausted 兜底文案') + + // D2、D3 是因为 halted 而被跳过、根本没发起请求的,error 字段应保持默认兜底文案。 + const d2Log = db.prepare("SELECT * FROM remind_logs WHERE anniversaryId = 'D2'").get() + const d3Log = db.prepare("SELECT * FROM remind_logs WHERE anniversaryId = 'D3'").get() + assert.strictEqual(d2Log.error, 'quota_exhausted', 'D2 从未真正发起请求,应为兜底文案') + assert.strictEqual(d3Log.error, 'quota_exhausted', 'D3 从未真正发起请求,应为兜底文案') }) test('非额度类错误只记 failed,不中止后续发送,也不动余额', async () => { diff --git a/server/test/wx.test.js b/server/test/wx.test.js index 24b39a7..d20ac39 100644 --- a/server/test/wx.test.js +++ b/server/test/wx.test.js @@ -13,23 +13,26 @@ test('微信返回非 0 errcode 时,抛出的 Error 对象应带上原始 errc const restoreGet = axios.get const restorePost = axios.post - // getAccessToken 走 axios.get,sendSubscribeMessage 走 axios.post,两个都要 mock - axios.get = async () => ({ data: { access_token: 'fake_token', expires_in: 7200 } }) - axios.post = async () => ({ data: { errcode: 43101, errmsg: 'user refuse to accept the msg' } }) + try { + // getAccessToken 走 axios.get,sendSubscribeMessage 走 axios.post,两个都要 mock + axios.get = async () => ({ data: { access_token: 'fake_token', expires_in: 7200 } }) + axios.post = async () => ({ data: { errcode: 43101, errmsg: 'user refuse to accept the msg' } }) - await assert.rejects( - () => wx.sendSubscribeMessage({ - touser: 'oTest', - page: 'pages/index/index', - templateId: 'tplTest', - data: {} - }), - (err) => { - assert.strictEqual(err.errcode, 43101, 'Error 对象应带上微信返回的原始 errcode,而不是靠字符串匹配') - return true - } - ) - - axios.get = restoreGet - axios.post = restorePost + await assert.rejects( + () => wx.sendSubscribeMessage({ + touser: 'oTest', + page: 'pages/index/index', + templateId: 'tplTest', + data: {} + }), + (err) => { + assert.strictEqual(err.errcode, 43101, 'Error 对象应带上微信返回的原始 errcode,而不是靠字符串匹配') + return true + } + ) + } finally { + // 断言先抛错也要恢复,避免污染同进程内后续用例 + axios.get = restoreGet + axios.post = restorePost + } })