$userId, 'item_id' => $itemId, 'instance_id' => null, 'quantity' => $originalQuantity, 'expire_at' => now()->addDays(30), 'is_frozen' => false, 'frozen_log_id' => null, ]); // 执行部分冻结操作 $result = ItemFreeze::freezeNormalItem( $userId, $itemId, $freezeQuantity, FREEZE_REASON_TYPE::TRADE_ORDER, 12345, 'order', null ); // 验证冻结操作成功 $this->assertTrue($result['success']); $this->assertEquals($freezeQuantity, $result['frozen_quantity']); // 验证数据库状态 // 原堆叠数量应该减少 $userItem->refresh(); $this->assertEquals($originalQuantity - $freezeQuantity, $userItem->quantity); $this->assertFalse($userItem->is_frozen); // 应该创建新的冻结堆叠 $frozenItem = ItemUser::where('user_id', $userId) ->where('item_id', $itemId) ->where('is_frozen', true) ->first(); $this->assertNotNull($frozenItem); $this->assertEquals($freezeQuantity, $frozenItem->quantity); // 验证事件触发 Event::assertDispatched(ItemQuantityChanged::class, 2); // 应该触发2个事件 // 验证第一个事件:原堆叠数量减少 Event::assertDispatched(ItemQuantityChanged::class, function ($event) use ($userId, $itemId, $userItem, $originalQuantity, $freezeQuantity) { return $event->userId === $userId && $event->itemId === $itemId && $event->userItemId === $userItem->id && $event->oldQuantity === $originalQuantity && $event->newQuantity === ($originalQuantity - $freezeQuantity) && $event->oldFrozenStatus === false && $event->newFrozenStatus === false && isset($event->options['change_type']) && $event->options['change_type'] === 'quantity_decrease'; }); // 验证第二个事件:新冻结堆叠创建 Event::assertDispatched(ItemQuantityChanged::class, function ($event) use ($userId, $itemId, $freezeQuantity) { return $event->userId === $userId && $event->itemId === $itemId && $event->oldQuantity === 0 // 新创建的物品,旧数量为0 && $event->newQuantity === $freezeQuantity && $event->oldFrozenStatus === null // 新创建的物品,旧冻结状态为null && $event->newFrozenStatus === true && isset($event->options['change_type']) && $event->options['change_type'] === 'frozen_item_create'; }); } finally { DB::rollBack(); } } /** * 测试全部冻结时的事件触发 * * 验证当进行全部冻结时: * 只触发冻结状态变更事件,不涉及数量变更 */ public function test_full_freeze_triggers_correct_event() { DB::beginTransaction(); try { $userId = 1002; $itemId = 2002; $quantity = 50; // 创建用户物品记录 $userItem = ItemUser::create([ 'user_id' => $userId, 'item_id' => $itemId, 'instance_id' => null, 'quantity' => $quantity, 'expire_at' => now()->addDays(30), 'is_frozen' => false, 'frozen_log_id' => null, ]); // 执行全部冻结操作 $result = ItemFreeze::freezeNormalItem( $userId, $itemId, $quantity, // 冻结全部数量 FREEZE_REASON_TYPE::ADMIN_FREEZE, null, null, 1 ); // 验证冻结操作成功 $this->assertTrue($result['success']); $this->assertEquals($quantity, $result['frozen_quantity']); // 验证数据库状态 $userItem->refresh(); $this->assertEquals($quantity, $userItem->quantity); // 数量不变 $this->assertTrue($userItem->is_frozen); // 冻结状态变为true // 验证事件触发 Event::assertDispatched(ItemQuantityChanged::class, 1); // 应该只触发1个事件 // 验证事件:冻结状态变更 Event::assertDispatched(ItemQuantityChanged::class, function ($event) use ($userId, $itemId, $userItem, $quantity) { return $event->userId === $userId && $event->itemId === $itemId && $event->userItemId === $userItem->id && $event->oldQuantity === $quantity && $event->newQuantity === $quantity // 数量不变 && $event->oldFrozenStatus === false && $event->newFrozenStatus === true && isset($event->options['change_type']) && $event->options['change_type'] === 'freeze_status_change'; }); } finally { DB::rollBack(); } } /** * 测试lastdata同步数据的正确性 * * 验证事件触发后,临时数据是否正确存储 */ public function test_lastdata_sync_data_correctness() { DB::beginTransaction(); try { $userId = 1003; $itemId = 2003; $originalQuantity = 80; $freezeQuantity = 25; // 创建用户物品记录 $userItem = ItemUser::create([ 'user_id' => $userId, 'item_id' => $itemId, 'instance_id' => null, 'quantity' => $originalQuantity, 'expire_at' => now()->addDays(30), 'is_frozen' => false, 'frozen_log_id' => null, ]); // 清空事件fake,使用真实的事件监听器 Event::fake([]); // 清空fake // 执行部分冻结操作 ItemFreeze::freezeNormalItem( $userId, $itemId, $freezeQuantity, FREEZE_REASON_TYPE::SYSTEM_FREEZE, null, null, null ); // 获取临时数据 $tempData = ItemTemp::getUserItemChanges($userId); // 验证临时数据包含了物品变更信息 $this->assertNotEmpty($tempData); $this->assertArrayHasKey($itemId, $tempData); $itemChange = $tempData[$itemId]; // 验证临时数据的正确性 // 注意:由于同一物品的多次变更会覆盖,这里应该是最后一次变更(冻结堆叠创建)的数据 $this->assertEquals($itemId, $itemChange->itemId); $this->assertEquals($freezeQuantity, $itemChange->newQuantity); $this->assertTrue($itemChange->newFrozenStatus); } finally { DB::rollBack(); } } }