Yii2使用Codeception单元测试时如何用Stub生成嵌套函数返回桩
Yii2框架下Codeception Stub嵌套链式调用模拟方案
失败原因说明
- 直接传入嵌套数组的方案:Yii ActiveRecord的关联属性返回值为对象实例,数组无法通过
->语法访问后续属性,会直接抛出错误。 - 加
get前缀模拟getter的方案:CodeceptionStub::make()的配置参数对应类的属性名(含Yii魔法方法支持的关联属性),添加get前缀仅会生成同名公共属性,无法对应关联属性的读取逻辑。
正确实现方案
方案1:逐层拆分模拟(推荐,易调试)
每层关联对象单独创建Stub实例,结构清晰便于后续校验调整:
// 模拟最内层商户详情对象,设置目标rule_type值 $merchantDetail = Stub::make(MerchantDetail::class, [ 'rule_type' => Billing::PERIODIC_MODE_DAILY, ]); // 模拟商户对象,关联detail属性返回上述详情实例 $merchant = Stub::make(Merchant::class, [ 'detail' => $merchantDetail, ]); // 模拟出账方对象,关联merchant属性返回上述商户实例 $biller = Stub::make(Biller::class, [ 'merchant' => $merchant, ]); // 生成最终账单测试桩 $billing = Stub::make(Billing::class, [ 'status' => Billing::STATUS_ACTIVE, 'set_periodic_by' => Billing::SET_PERIODIC_BY_MERCHANT, 'biller' => $biller, ]);
方案2:嵌套写法
无需拆分变量,直接嵌套生成Stub实例:
$billing = Stub::make(Billing::class, [ 'status' => Billing::STATUS_ACTIVE, 'set_periodic_by' => Billing::SET_PERIODIC_BY_MERCHANT, 'biller' => Stub::make(Biller::class, [ 'merchant' => Stub::make(Merchant::class, [ 'detail' => Stub::make(MerchantDetail::class, [ 'rule_type' => Billing::PERIODIC_MODE_DAILY, ]) ]) ]) ]);
补充建议
如果业务代码中是显式调用getter方法(如$billing->getBiller()而非$billing->biller),可以通过闭包定义方法返回值:
$billing = Stub::make(Billing::class, [ 'getBiller' => function() { return Stub::make(Biller::class, [ 'getMerchant' => function() { return Stub::make(Merchant::class, [ 'getDetail' => function() { return Stub::make(MerchantDetail::class, [ 'rule_type' => Billing::PERIODIC_MODE_DAILY, ]); } ]); } ]); } ]);
内容的提问来源于stack exchange,提问作者Prabowo Murti
相关产品推荐
相关产品推荐

