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

如何在Laravel中使用Mockery模拟StripeClient类的构造函数

Laravel中Mockery模拟StripeClient(带构造参数)的解决方案

在Laravel单元测试中使用Mockery模拟StripeClient时,若通过app(StripeClient::class, ['config' => $key])初始化客户端,会触发真实构造函数执行(导致无效密钥错误),即使尝试模拟__construct也无效。但不传构造参数时模拟正常。

问题根源

当调用app(Class::class, $parameters)时,Laravel容器会忽略已绑定的实例,而是尝试用传入的参数重新实例化原始类,因此之前绑定的mock不会被使用。

解决方案1:构造Mock时指定匹配的构造参数

直接在创建Mockery实例时传入构造参数,确保容器解析时匹配并使用该mock:

// 创建带构造参数匹配的StripeClient mock
$stripeMock = \Mockery::mock(StripeClient::class, ['config' => $this->stripeSecretKey]);

// 模拟request方法(对应balance->retrieve的底层调用)
$stripeMock->shouldReceive('request')
    ->zeroOrMoreTimes()
    ->andReturn([
        'available' => [
            'amount' => 1000,
        ],
        'livemode' => false,
    ]);

// 将mock绑定到Laravel容器
$this->app->instance(StripeClient::class, $stripeMock);

解决方案2:使用Laravel测试助手mock()(Laravel 8+)

利用Laravel内置的测试助手简化mock流程,同时处理构造参数:

$this->mock(StripeClient::class, function ($mock) {
    // 允许模拟构造函数,匹配传入的config参数
    $mock->makePartial()->shouldReceive('__construct')
        ->with(['config' => $this->stripeSecretKey])
        ->andReturnSelf();

    // 模拟request方法返回预期数据
    $mock->shouldReceive('request')
        ->zeroOrMoreTimes()
        ->andReturn([
            'available' => [
                'amount' => 1000,
            ],
            'livemode' => false,
        ]);
});

更优方案:依赖注入替代app()助手调用

修改服务类,通过构造函数依赖注入StripeClient,避免直接在代码中调用app(),让测试更灵活:

修改服务类

class StripeService {
    protected $stripeClient;

    // 构造函数注入StripeClient
    public function __construct(StripeClient $stripeClient) {
        $this->stripeClient = $stripeClient;
    }

    public function getStripeBalance(string $stripeAccountId): array {
        return $this->stripeClient
            ->balance
            ->retrieve([], ['stripe_account' => $stripeAccountId])
            ->toArray();
    }
}

测试代码

// 创建mock并设置预期行为
$stripeMock = \Mockery::mock(StripeClient::class);
$stripeMock->shouldReceive('request')
    ->zeroOrMoreTimes()
    ->andReturn([
        'available' => ['amount' => 1000],
        'livemode' => false,
    ]);

// 直接将mock注入服务类
$stripeService = new StripeService($stripeMock);
$balance = $stripeService->getStripeBalance('acc_123456');

// 断言结果符合预期
$this->assertEquals(1000, $balance['available'][0]['amount']);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:58:30