"""斗鱼写路径契约:锁单/支付编排走 mock 客户端,不打真实兑换。""" from unittest.mock import Mock from tests.support.db import get_test_engine, make_test_session from web.backend.models import Account, DouyuGoodsSnapshot, DouyuTask, User from web.backend.services.douyu_runner import DouyuBatchRunner class TestDouyuWritePathContracts: def setup_method(self): self.engine = get_test_engine() self.session = make_test_session(self.engine) self.user = User(username="operator", password_hash="hash", role="super_admin") self.account = Account( username="dyuser", password="pw", email="a@example.com", email_password="em", ) self.session.add_all([self.user, self.account]) self.session.commit() self.session.add( DouyuGoodsSnapshot( commodity_id="bag10", name="套装-兔兔白日梦", raw={"name": "套装-兔兔白日梦"}, ) ) self.session.commit() def teardown_method(self): self.session.close() def _runner(self, task_type: str) -> DouyuBatchRunner: return DouyuBatchRunner(db=self.session, batch_id="batch1", task_type=task_type) def _task(self, task_type: str, payload: dict) -> DouyuTask: task = DouyuTask( batch_id="batch1", account_id=self.account.id, task_type=task_type, handbook_scope="elite", status="running", result={"payload": payload}, created_by=self.user.id, ) self.session.add(task) self.session.commit() return task def test_lock_goods_records_order_without_paying(self): task = self._task("lock_goods", {"commodity_id": "bag10", "num": 1}) runner = self._runner("lock_goods") client = Mock() client.create_exchange_order.return_value = { "order_id": "5874", "expire_seconds": "300", } runner._client = Mock(return_value=client) runner._execute_lock_goods( self.session, task, self.account, "acf_uid=100", {"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"}, ) self.session.refresh(task) self.session.refresh(self.account) assert task.status == "success" assert task.result["order_id"] == "5874" # 锁单是**流程痕迹**,不是账号状态 —— S6 起不再写 bind_status # (动作本身在 douyu_tasks 与 account_events 里都能查)。 assert self.account.bind_status != "goods_locked" client.create_exchange_order.assert_called_once() client.pay_exchange_order.assert_not_called() def test_pay_locked_order_uses_existing_order_id(self): task = self._task( "pay_locked_order", {"order_id": "5874", "commodity_id": "bag10"}, ) runner = self._runner("pay_locked_order") client = Mock() client.pay_exchange_order.return_value = { "exchange_id": "11098933", "commodity_image": "https://example.test/item.png", "exchange_num": 1, } runner._client = Mock(return_value=client) runner._refresh_account_points = Mock(return_value={"points": 1280}) runner._execute_pay_locked_order( self.session, task, self.account, "acf_uid=100", {"manual_id": "G4KA4Qnz4LDp7", "rid": "9263298"}, ) self.session.refresh(task) assert task.status == "success" assert task.result["exchange_id"] == "11098933" client.pay_exchange_order.assert_called_once() client.create_exchange_order.assert_not_called()