disasterRemovalLogic = new DisasterRemovalLogic(); } /** * 测试概率计算逻辑 */ public function testProbabilityCalculation() { // 使用反射来测试私有方法 $reflection = new \ReflectionClass(DisasterRemovalLogic::class); $rollSuccessMethod = $reflection->getMethod('rollSuccess'); $rollSuccessMethod->setAccessible(true); // 测试0%成功率 $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 0); $this->assertFalse($result, '0%成功率应该总是失败'); // 测试100%成功率 $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 100); $this->assertTrue($result, '100%成功率应该总是成功'); // 测试负数成功率 $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, -10); $this->assertFalse($result, '负数成功率应该总是失败'); // 测试超过100%的成功率 $result = $rollSuccessMethod->invoke($this->disasterRemovalLogic, 150); $this->assertTrue($result, '超过100%的成功率应该总是成功'); } /** * 测试灾害类型映射 */ public function testDisasterTypeMapping() { $reflection = new \ReflectionClass(DisasterRemovalLogic::class); // 获取常量 $attributesConstant = $reflection->getConstant('DISASTER_ITEM_ATTRIBUTES'); $namesConstant = $reflection->getConstant('DISASTER_ACTION_NAMES'); // 验证映射关系 $this->assertArrayHasKey(DISASTER_TYPE::DROUGHT->value, $attributesConstant); $this->assertArrayHasKey(DISASTER_TYPE::PEST->value, $attributesConstant); $this->assertArrayHasKey(DISASTER_TYPE::WEED->value, $attributesConstant); $this->assertEquals('fram_drought_rate', $attributesConstant[DISASTER_TYPE::DROUGHT->value]); $this->assertEquals('fram_pesticide_rate', $attributesConstant[DISASTER_TYPE::PEST->value]); $this->assertEquals('fram_weedicide_rate', $attributesConstant[DISASTER_TYPE::WEED->value]); $this->assertEquals('浇水', $namesConstant[DISASTER_TYPE::DROUGHT->value]); $this->assertEquals('除虫', $namesConstant[DISASTER_TYPE::PEST->value]); $this->assertEquals('除草', $namesConstant[DISASTER_TYPE::WEED->value]); } /** * 测试不支持的灾害类型 */ public function testUnsupportedDisasterType() { $this->expectException(LogicException::class); $this->expectExceptionMessage('不支持的灾害类型: 999'); // 开启事务以满足事务检查要求 DB::beginTransaction(); try { $this->disasterRemovalLogic->removeDisaster(1, 1, 1, 999, 'test'); } finally { DB::rollBack(); } } /** * 测试事务检查 */ public function testTransactionCheck() { $this->expectException(\LogicException::class); $this->expectExceptionMessage('transaction level is 0'); // 不开启事务,应该抛出异常 $this->disasterRemovalLogic->removeDisaster( 1, 1, 1, DISASTER_TYPE::PEST->value, 'test' ); } /** * 测试获取物品成功率 */ public function testGetItemSuccessRate() { $reflection = new \ReflectionClass(DisasterRemovalLogic::class); $getItemSuccessRateMethod = $reflection->getMethod('getItemSuccessRate'); $getItemSuccessRateMethod->setAccessible(true); // Mock ItemService $this->mock(ItemService::class, function ($mock) { $mock->shouldReceive('getItemNumericAttribute') ->with(123, 'fram_pesticide_rate', 0) ->andReturn(80); }); $result = $getItemSuccessRateMethod->invoke( $this->disasterRemovalLogic, 123, DISASTER_TYPE::PEST->value ); $this->assertEquals(80, $result); } /** * 测试事务检查要求 */ public function testTransactionRequirement() { // Mock ItemService $this->mock(ItemService::class, function ($mock) { $mock->shouldReceive('getItemNumericAttribute') ->with(123, 'fram_pesticide_rate', 0) ->andReturn(80); }); // 开启事务 DB::beginTransaction(); try { // 这个测试主要验证逻辑层不再进行验证,专注于业务逻辑 $this->disasterRemovalLogic->removeDisaster( 1, // userId 1, // landId 123, // itemId DISASTER_TYPE::PEST->value, 'test' ); // 由于没有实际的作物数据,这里会失败,但我们主要测试事务检查通过 $this->fail('应该因为没有作物数据而失败'); } catch (\Exception $e) { // 预期会失败,因为没有实际的作物数据 $this->assertStringContainsString('灾害清理失败', $e->getMessage()); } finally { DB::rollBack(); } } }