Laravel中如何正确Mock Stripe PHP包的Stripe类?
如何正确Mock Stripe类来测试setApiKey方法?
问题根源
你遇到的问题很典型:你的StripeBiller类里是直接在setApiKey方法内new了一个真实的Stripe实例,而你测试中Mock的Stripe对象和这个实例完全是两个独立的东西。所以不管你怎么Mock,实际执行的都是真实的Stripe类,Mock的setApiKey方法自然不会被调用,就出现了调用次数不匹配的错误。
解决步骤
要解决这个问题,核心是让StripeBiller的依赖(也就是Stripe类)可以被替换,最直接的方式就是依赖注入。
1. 修改StripeBiller类,通过构造函数注入Stripe实例
把原来直接new的方式改成从外部传入Stripe对象:
class StripeBiller { private $stripe; // 构造函数注入Stripe依赖 public function __construct(Stripe $stripe) { $this->stripe = $stripe; } public function setApiKey() { $this->stripe->setApiKey(env('STRIPE_API_KEY')); } }
2. 更新测试代码,注入Mock的Stripe对象
现在测试的时候,你可以把Mock的Stripe实例传给StripeBiller,这样调用setApiKey时就会使用你Mock的对象了:
public function test_api_key_is_set() { // 创建Stripe的Mock,并指定预期调用 $stripeMock = $this->mock(Stripe::class, function ($mock) { // 可以加上with来验证传入的参数是否正确 $mock->shouldReceive('setApiKey') ->once() ->with(env('STRIPE_API_KEY')); }); // 把Mock注入到StripeBiller实例中 $biller = new StripeBiller($stripeMock); $biller->setApiKey(); }
额外说明
如果你暂时不想修改构造函数,也可以考虑用工厂方法或者依赖容器来提供Stripe实例,但构造注入是最简洁、最易维护的方式,也是测试友好的最佳实践之一。这样做不仅能解决当前的测试问题,还能让你的代码耦合度更低,扩展性更好。
内容的提问来源于stack exchange,提问作者Jamie Woods
相关产品推荐
相关产品推荐

