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

如何在PEST PHP测试中无Mock测试Laravel Cashier结账重定向?

问题:Laravel Cashier订阅接口的无Mock测试方案

我有一个用于引导用户跳转到Stripe结账页的subscribeToPlan方法,代码如下:

public function subscribeToPlan(StripePlan $plan): \Laravel\Cashier\Checkout
{
    return auth()->user()->newSubscription('default', $plan->plan_id)->checkout([
        'success_url' => route('admin.plans.index'),
        'cancel_url' => route('admin.plans.index'),
    ]);
}

对应的PEST测试用例:

test('User can subscribe to the Plan', function () {
    $plan = Plan::query()->first();
    $checkout = $this->actingAs($this->user)
        ->get(route('admin.plans.purchase', $plan));
   $this->assertInstanceOf(Checkout::class, $checkout);
});

实际运行时发现,subscribeToPlan方法返回的并非声明的Checkout实例,而是Illuminate\Http\RedirectResponse——这是因为Laravel会自动将Cashier的Checkout对象转换为重定向响应。现在需要编写不使用Mock的正确测试用例。


解决方法

因为不能Mock,我们需要测试接口的实际行为而非返回的实例类型,核心是验证重定向的正确性:

  • 断言响应是重定向状态(302)
  • 验证重定向目标是Stripe结账域名
  • 可选:校验URL中包含正确的计划ID、回调地址等关键参数

修改后的测试代码:

test('User can subscribe to the Plan', function () {
    // 准备测试数据
    $plan = Plan::query()->first();
    $successUrl = route('admin.plans.index');
    $cancelUrl = route('admin.plans.index');

    // 发起请求
    $response = $this->actingAs($this->user)
        ->get(route('admin.plans.purchase', $plan));

    // 1. 断言是重定向响应
    $response->assertRedirect();
    $this->assertInstanceOf(Illuminate\Http\RedirectResponse::class, $response);

    // 2. 断言重定向到Stripe结账域名
    $redirectUrl = $response->headers->get('Location');
    $this->str($redirectUrl)->contains('checkout.stripe.com');

    // 3. 可选:校验URL中包含有效的Stripe会话ID
    parse_str(parse_url($redirectUrl, PHP_URL_QUERY), $queryParams);
    $this->assertNotEmpty($queryParams['session_id']);

    // (进阶)如果需要验证计划匹配,可通过Stripe测试API获取会话详情
    // 需要提前配置Stripe测试密钥
    // $session = \Stripe\Checkout\Session::retrieve($queryParams['session_id']);
    // $this->assertEquals($plan->plan_id, $session->line_items->data[0]->price->product);
});

关键说明

  1. Laravel Cashier的checkout()方法返回的Checkout对象实现了Responsable接口,Laravel会自动将其解析为RedirectResponse,所以控制器实际返回的是重定向而非原始Checkout实例。
  2. 不使用Mock的情况下,测试的核心是验证业务行为:用户被正确引导到Stripe结账页,且跳转参数符合预期。
  3. 如果需要验证计划ID等细节,可以通过Stripe的测试API获取结账会话详情,但需要提前配置测试环境的Stripe密钥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:52:13