You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化计费代码减少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的返回值,精准模拟节假日/非节假日场景。
  • 配合Mockformat('l')、gte、lt方法,可以隔离其他变量,单独验证目标分支的逻辑。
  • 测试需覆盖所有业务分支:VIP、节假日/周末非VIP、工作日高峰非VIP、工作日非高峰非VIP,确保逻辑无遗漏。

内容的提问来源于stack exchange,提问作者JHee Oh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:15:43