ItemFreezeSyncFixTest.php 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. namespace Tests\Unit\GameItems;
  3. use App\Module\Game\Logics\ItemTemp;
  4. use App\Module\GameItems\Enums\FREEZE_REASON_TYPE;
  5. use App\Module\GameItems\Events\ItemQuantityChanged;
  6. use App\Module\GameItems\Logics\ItemFreeze;
  7. use App\Module\GameItems\Models\ItemUser;
  8. use Illuminate\Support\Facades\DB;
  9. use Illuminate\Support\Facades\Event;
  10. use Tests\TestCase;
  11. /**
  12. * 物品冻结同步修复验证测试
  13. *
  14. * 验证修复后的物品冻结拆堆同步功能
  15. */
  16. class ItemFreezeSyncFixTest extends TestCase
  17. {
  18. protected function setUp(): void
  19. {
  20. parent::setUp();
  21. }
  22. /**
  23. * 测试拆堆冻结后的lastdata同步修复
  24. *
  25. * 验证拆堆时能正确同步两个物品堆的状态到lastdata
  26. */
  27. public function test_split_stack_freeze_lastdata_sync_fix()
  28. {
  29. DB::beginTransaction();
  30. try {
  31. $userId = 9999; // 使用一个不存在物品记录的用户ID
  32. $itemId = 2; // 使用现有的萝卜物品
  33. $originalQuantity = 200;
  34. $freezeQuantity = 80;
  35. // 清理可能存在的临时数据
  36. ItemTemp::clearUserItemChanges($userId);
  37. // 创建测试用户物品记录
  38. $userItem = ItemUser::create([
  39. 'user_id' => $userId,
  40. 'item_id' => $itemId,
  41. 'instance_id' => null,
  42. 'quantity' => $originalQuantity,
  43. 'expire_at' => now()->addDays(30),
  44. 'is_frozen' => false,
  45. 'frozen_log_id' => null,
  46. ]);
  47. // 启用真实事件监听(不使用fake)
  48. $originalEventDispatcher = app('events');
  49. // 执行部分冻结操作(会触发拆堆)
  50. $result = ItemFreeze::freezeNormalItem(
  51. $userId,
  52. $itemId,
  53. $freezeQuantity,
  54. FREEZE_REASON_TYPE::TRADE_ORDER,
  55. 12345,
  56. 'test_order',
  57. null
  58. );
  59. // 验证冻结操作成功
  60. $this->assertTrue($result['success']);
  61. $this->assertEquals($freezeQuantity, $result['frozen_quantity']);
  62. // 验证临时数据中包含两个物品堆的变更信息
  63. $itemChanges = ItemTemp::getUserItemChanges($userId);
  64. $this->assertCount(2, $itemChanges, '应该有两个物品堆的变更记录');
  65. // 验证原堆叠的变更记录
  66. $originalStackChange = null;
  67. $frozenStackChange = null;
  68. foreach ($itemChanges as $change) {
  69. if ($change->userItemId === $userItem->id) {
  70. $originalStackChange = $change;
  71. } else {
  72. $frozenStackChange = $change;
  73. }
  74. }
  75. $this->assertNotNull($originalStackChange, '应该有原堆叠的变更记录');
  76. $this->assertNotNull($frozenStackChange, '应该有冻结堆叠的变更记录');
  77. // 验证原堆叠变更记录的正确性
  78. $this->assertEquals($itemId, $originalStackChange->itemId);
  79. $this->assertEquals($originalQuantity, $originalStackChange->oldQuantity);
  80. $this->assertEquals($originalQuantity - $freezeQuantity, $originalStackChange->newQuantity);
  81. $this->assertEquals(-$freezeQuantity, $originalStackChange->changeAmount);
  82. $this->assertFalse($originalStackChange->oldFrozenStatus);
  83. $this->assertFalse($originalStackChange->newFrozenStatus);
  84. // 验证冻结堆叠变更记录的正确性
  85. $this->assertEquals($itemId, $frozenStackChange->itemId);
  86. $this->assertEquals(0, $frozenStackChange->oldQuantity);
  87. $this->assertEquals($freezeQuantity, $frozenStackChange->newQuantity);
  88. $this->assertEquals($freezeQuantity, $frozenStackChange->changeAmount);
  89. $this->assertNull($frozenStackChange->oldFrozenStatus);
  90. $this->assertTrue($frozenStackChange->newFrozenStatus);
  91. // 验证数据库中的实际状态
  92. $userItem->refresh();
  93. $this->assertEquals($originalQuantity - $freezeQuantity, $userItem->quantity);
  94. $this->assertFalse($userItem->is_frozen);
  95. // 查找新创建的冻结堆叠
  96. $frozenItem = ItemUser::where('user_id', $userId)
  97. ->where('item_id', $itemId)
  98. ->where('is_frozen', true)
  99. ->where('quantity', $freezeQuantity)
  100. ->first();
  101. $this->assertNotNull($frozenItem, '应该有新创建的冻结堆叠');
  102. $this->assertEquals($freezeQuantity, $frozenItem->quantity);
  103. $this->assertTrue($frozenItem->is_frozen);
  104. } finally {
  105. DB::rollBack();
  106. }
  107. }
  108. /**
  109. * 测试全部冻结时的单堆同步
  110. *
  111. * 验证全部冻结时只有一个物品堆状态变更
  112. */
  113. public function test_full_freeze_single_stack_sync()
  114. {
  115. DB::beginTransaction();
  116. try {
  117. $userId = 9998; // 使用一个不存在物品记录的用户ID
  118. $itemId = 3; // 使用现有的辣椒物品
  119. $quantity = 50;
  120. // 清理可能存在的临时数据
  121. ItemTemp::clearUserItemChanges($userId);
  122. // 创建测试用户物品记录
  123. $userItem = ItemUser::create([
  124. 'user_id' => $userId,
  125. 'item_id' => $itemId,
  126. 'instance_id' => null,
  127. 'quantity' => $quantity,
  128. 'expire_at' => now()->addDays(30),
  129. 'is_frozen' => false,
  130. 'frozen_log_id' => null,
  131. ]);
  132. // 执行全部冻结操作(不会拆堆)
  133. $result = ItemFreeze::freezeNormalItem(
  134. $userId,
  135. $itemId,
  136. $quantity, // 全部冻结
  137. FREEZE_REASON_TYPE::TRADE_ORDER,
  138. 12346,
  139. 'test_order',
  140. null
  141. );
  142. // 验证冻结操作成功
  143. $this->assertTrue($result['success']);
  144. $this->assertEquals($quantity, $result['frozen_quantity']);
  145. // 验证临时数据中只有一个物品堆的变更信息
  146. $itemChanges = ItemTemp::getUserItemChanges($userId);
  147. $this->assertCount(1, $itemChanges, '应该只有一个物品堆的变更记录');
  148. $change = $itemChanges[0];
  149. $this->assertEquals($userItem->id, $change->userItemId);
  150. $this->assertEquals($itemId, $change->itemId);
  151. $this->assertEquals($quantity, $change->oldQuantity);
  152. $this->assertEquals($quantity, $change->newQuantity);
  153. $this->assertEquals(0, $change->changeAmount);
  154. $this->assertFalse($change->oldFrozenStatus);
  155. $this->assertTrue($change->newFrozenStatus);
  156. // 验证数据库中的实际状态
  157. $userItem->refresh();
  158. $this->assertEquals($quantity, $userItem->quantity);
  159. $this->assertTrue($userItem->is_frozen);
  160. } finally {
  161. DB::rollBack();
  162. }
  163. }
  164. }