优化计费代码减少if-else,实现isHoliday方法的Mock单元测试
简化计费逻辑与单元测试实现
一、简化后的计费逻辑
把嵌套的if-else扁平化,用更直观的条件组合减少层级,同时保留原业务规则:
// 优先处理VIP免单场景 if ($request->isVip == 1) { $fee = 0; } else { // 整合非VIP的计费条件:节假日/周末 或 非高峰时段,费用110;否则0 $chargeFullFee = in_array($now->format('l'), ['Saturday','Sunday']) || $now->isHoliday() || !($now->gte(Carbon::parse('8:45')) && $now->lt(Carbon::parse('18:00'))); $fee = $chargeFullFee ? 110 : 0; }
或者用三元表达式进一步压缩(可读性仍有保障):
$fee = $request->isVip == 1 ? 0 : ( in_array($now->format('l'), ['Saturday','Sunday']) || $now->isHoliday() ? 110 : ($now->gte(Carbon::parse('8:45')) && $now->lt(Carbon::parse('18:00')) ? 0 : 110) );
二、节假日场景单元测试(Mock实现)
以PHPUnit + Mockery(Laravel生态常用Mock工具)为例,实现isHoliday方法的Mock:
1. 核心测试代码示例
use Mockery; use Carbon\Carbon; use PHPUnit\Framework\TestCase; use App\Services\BillingService; // 假设计费逻辑封装在这个类中 class BillingServiceTest extends TestCase { protected function tearDown(): void { Mockery::close(); // 清理Mock实例 } // 测试:非VIP用户在节假日的计费 public function test_non_vip_holiday_fee() { // Mock请求对象:非VIP $request = Mockery::mock(\Illuminate\Http\Request::class); $request->isVip = 0; // Mock Carbon实例,强制isHoliday返回true,同时模拟为工作日(排除周末干扰) $now = Mockery::mock(Carbon::class); $now->shouldReceive('format')->with('l')->andReturn('Monday'); $now->shouldReceive('isHoliday')->andReturn(true); // 执行计费逻辑 $service = new BillingService(); $fee = $service->calculateFee($request, $now); // 断言结果符合预期 $this->assertEquals(110, $fee); } // 测试:非VIP用户在非节假日工作日的高峰时段计费 public function test_non_vip_workday_peak_hour_fee() { $request = Mockery::mock(\Illuminate\Http\Request::class); $request->isVip = 0; $now = Mockery::mock(Carbon::class); $now->shouldReceive('format')->with('l')->andReturn('Monday'); $now->shouldReceive('isHoliday')->andReturn(false); // Mock高峰时段(8:45-18:00之间) $now->shouldReceive('gte')->with(Carbon::parse('8:45'))->andReturn(true); $now->shouldReceive('lt')->with(Carbon::parse('18:00'))->andReturn(true); $service = new BillingService(); $fee = $service->calculateFee($request, $now); $this->assertEquals(0, $fee); } }
2. Mock关键说明
- 通过
$now->shouldReceive('isHoliday')->andReturn(true/false)直接控制isHoliday的返回值,精准模拟节假日/非节假日场景。 - 配合Mock
format('l')、gte、lt方法,可以隔离其他变量,单独验证目标分支的逻辑。 - 测试需覆盖所有业务分支:VIP、节假日/周末非VIP、工作日高峰非VIP、工作日非高峰非VIP,确保逻辑无遗漏。
内容的提问来源于stack exchange,提问作者JHee Oh
相关产品推荐
相关产品推荐

