在PHP Codeception中如何模拟Stripe类?
Stripe Customer类单元测试模拟报错解决方法
报错原因
你遇到的报错:
Could not add property name, class Stripe\Customer implements __set method, and no name property exists
是因为Stripe官方SDK的Stripe\Customer类继承自Stripe\StripeObject,所有业务属性(比如name、email、id等)都没有显式声明为类的成员属性,统一通过魔术方法__get/__set存取。Codeception的makeEmpty/makeEmptyExcept方法默认会尝试给对象挂载public属性,当检测到类实现了__set且对应属性不存在时就会抛出上述错误。
可用解决方案
方案1:直接构造原生Stripe实例(最推荐)
Stripe的所有资源类都支持传入属性数组直接初始化,实例行为和API返回的真实对象完全一致,不需要依赖测试框架的模拟能力就能满足读属性的需求:
$customer = new \Stripe\Customer([ 'name' => $cust_nm, // 其他需要的属性可直接追加到数组中 ]);
方案2:模拟魔术方法__get
如果必须使用Codeception模拟对象(比如需要验证方法调用次数等场景),可以直接定义__get方法的返回逻辑匹配你的需求:
$customer = $this->makeEmpty(Customer::class, [ '__get' => function (string $property) use ($cust_nm) { return match($property) { 'name' => $cust_nm, // 其他需要返回的属性在这里追加匹配规则 default => null }; } ]);
方案3:开启强制属性赋值
Codeception的makeEmpty方法支持第三个$force参数,设置为true时会跳过__set检查,强制给对象挂载指定属性:
$customer = $this->makeEmpty(Customer::class, ['name' => $cust_nm], true);
注意该方案兼容性较低,若被测试代码依赖StripeObject的其他内置魔术方法逻辑,强制挂载的属性可能出现不符合预期的行为。
内容的提问来源于stack exchange,提问作者Papa Joe Dee
相关产品推荐
相关产品推荐

