DisasterRemovalLogicTest.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <?php
  2. namespace Tests\Unit\Farm;
  3. use Tests\TestCase;
  4. use App\Module\Farm\Logics\DisasterRemovalLogic;
  5. use App\Module\Farm\Enums\DISASTER_TYPE;
  6. use App\Module\GameItems\Services\ItemService;
  7. use Illuminate\Foundation\Testing\RefreshDatabase;
  8. use Illuminate\Support\Facades\DB;
  9. use UCore\Exception\LogicException;
  10. /**
  11. * 灾害去除逻辑测试
  12. */
  13. class DisasterRemovalLogicTest extends TestCase
  14. {
  15. use RefreshDatabase;
  16. private DisasterRemovalLogic $disasterRemovalLogic;
  17. protected function setUp(): void
  18. {
  19. parent::setUp();
  20. $this->disasterRemovalLogic = new DisasterRemovalLogic();
  21. }
  22. /**
  23. * 测试概率计算逻辑
  24. */
  25. public function testProbabilityCalculation()
  26. {
  27. // 使用反射来测试私有方法
  28. $reflection = new \ReflectionClass(DisasterRemovalLogic::class);
  29. $rollSuccessMethod = $reflection->getMethod('rollSuccess');
  30. $rollSuccessMethod->setAccessible(true);
  31. // 测试0%成功率
  32. $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 0);
  33. $this->assertFalse($result, '0%成功率应该总是失败');
  34. // 测试100%成功率
  35. $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 100);
  36. $this->assertTrue($result, '100%成功率应该总是成功');
  37. // 测试负数成功率
  38. $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, -10);
  39. $this->assertFalse($result, '负数成功率应该总是失败');
  40. // 测试超过100%的成功率
  41. $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 150);
  42. $this->assertTrue($result, '超过100%的成功率应该总是成功');
  43. }
  44. /**
  45. * 测试灾害类型映射
  46. */
  47. public function testDisasterTypeMapping()
  48. {
  49. $reflection = new \ReflectionClass(DisasterRemovalLogic::class);
  50. // 获取常量
  51. $attributesConstant = $reflection->getConstant('DISASTER_ITEM_ATTRIBUTES');
  52. $namesConstant = $reflection->getConstant('DISASTER_ACTION_NAMES');
  53. // 验证映射关系
  54. $this->assertArrayHasKey(DISASTER_TYPE::DROUGHT->value, $attributesConstant);
  55. $this->assertArrayHasKey(DISASTER_TYPE::PEST->value, $attributesConstant);
  56. $this->assertArrayHasKey(DISASTER_TYPE::WEED->value, $attributesConstant);
  57. $this->assertEquals('fram_drought_rate', $attributesConstant[DISASTER_TYPE::DROUGHT->value]);
  58. $this->assertEquals('fram_pesticide_rate', $attributesConstant[DISASTER_TYPE::PEST->value]);
  59. $this->assertEquals('fram_weedicide_rate', $attributesConstant[DISASTER_TYPE::WEED->value]);
  60. $this->assertEquals('浇水', $namesConstant[DISASTER_TYPE::DROUGHT->value]);
  61. $this->assertEquals('除虫', $namesConstant[DISASTER_TYPE::PEST->value]);
  62. $this->assertEquals('除草', $namesConstant[DISASTER_TYPE::WEED->value]);
  63. }
  64. /**
  65. * 测试不支持的灾害类型
  66. */
  67. public function testUnsupportedDisasterType()
  68. {
  69. $this->expectException(LogicException::class);
  70. $this->expectExceptionMessage('不支持的灾害类型: 999');
  71. // 开启事务以满足事务检查要求
  72. DB::beginTransaction();
  73. try {
  74. $this->disasterRemovalLogic->removeDisaster(1, 1, 1, 999, 'test');
  75. } finally {
  76. DB::rollBack();
  77. }
  78. }
  79. /**
  80. * 测试事务检查
  81. */
  82. public function testTransactionCheck()
  83. {
  84. $this->expectException(\LogicException::class);
  85. $this->expectExceptionMessage('transaction level is 0');
  86. // 不开启事务,应该抛出异常
  87. $this->disasterRemovalLogic->removeDisaster(
  88. 1,
  89. 1,
  90. 1,
  91. DISASTER_TYPE::PEST->value,
  92. 'test'
  93. );
  94. }
  95. /**
  96. * 测试获取物品成功率
  97. */
  98. public function testGetItemSuccessRate()
  99. {
  100. $reflection = new \ReflectionClass(DisasterRemovalLogic::class);
  101. $getItemSuccessRateMethod = $reflection->getMethod('getItemSuccessRate');
  102. $getItemSuccessRateMethod->setAccessible(true);
  103. // Mock ItemService
  104. $this->mock(ItemService::class, function ($mock) {
  105. $mock->shouldReceive('getItemNumericAttribute')
  106. ->with(123, 'fram_pesticide_rate', 0)
  107. ->andReturn(80);
  108. });
  109. $result = $getItemSuccessRateMethod->invoke(
  110. $this->disasterRemovalLogic,
  111. 123,
  112. DISASTER_TYPE::PEST->value
  113. );
  114. $this->assertEquals(80, $result);
  115. }
  116. /**
  117. * 测试事务检查要求
  118. */
  119. public function testTransactionRequirement()
  120. {
  121. // Mock ItemService
  122. $this->mock(ItemService::class, function ($mock) {
  123. $mock->shouldReceive('getItemNumericAttribute')
  124. ->with(123, 'fram_pesticide_rate', 0)
  125. ->andReturn(80);
  126. });
  127. // 开启事务
  128. DB::beginTransaction();
  129. try {
  130. // 这个测试主要验证逻辑层不再进行验证,专注于业务逻辑
  131. $this->disasterRemovalLogic->removeDisaster(
  132. 1, // userId
  133. 1, // landId
  134. 123, // itemId
  135. DISASTER_TYPE::PEST->value,
  136. 'test'
  137. );
  138. // 由于没有实际的作物数据,这里会失败,但我们主要测试事务检查通过
  139. $this->fail('应该因为没有作物数据而失败');
  140. } catch (\Exception $e) {
  141. // 预期会失败,因为没有实际的作物数据
  142. $this->assertStringContainsString('灾害清理失败', $e->getMessage());
  143. } finally {
  144. DB::rollBack();
  145. }
  146. }
  147. }