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

无法通过Codeception保存新ActiveRecord记录,请求技术协助

解决Yii2单元测试中BlamemableBehavior导致created_by不能为空的问题

我之前在做Yii2单元测试时也踩过这个一模一样的坑!咱们来一步步拆解问题,找到解决办法:

问题根源

BlamemableBehavior的核心逻辑是从Yii::$app->user获取当前登录用户ID来填充created_by字段,但单元测试环境默认是没有登录用户的,所以行为会把created_by设为null,而你的数据库字段又设置了非空约束,就触发了IntegrityException。

你说手动传值和解绑行为没用,大概率是操作时机不对或者方法没到位,下面给你几个靠谱的解决方案:


方案1:测试时模拟登录用户(最推荐)

这是最贴近真实业务场景的做法,让BlamemableBehavior能正常工作:
在你的测试方法里,先登录一个测试用户,再创建订单:

// 假设你有一个预先创建好的测试用户,ID为1
$testUser = \frontend\models\User::findOne(1);
// 模拟登录
Yii::$app->user->login($testUser);

// 接下来创建订单,created_by会被行为自动填充
$order = new \frontend\models\Order();
$order->attributes = [
    // 其他字段赋值
    'order_no' => 'TEST_001',
    'amount' => 99.99,
];
$order->save();

这样行为能正常获取到用户ID,就不会出现null的情况了。

方案2:正确解绑BlamemableBehavior

如果你确实需要手动控制created_by的值,要注意解绑行为的时机——必须在赋值和保存之前解绑:

$order = new \frontend\models\Order();
// 解绑行为,注意行为的名称默认是'blameable',如果你的模型里自定义了名称要对应修改
$order->detachBehavior('blameable');

// 手动设置created_by
$order->created_by = 1;
// 其他字段赋值
$order->order_no = 'TEST_002';
$order->amount = 199.99;

$order->save();

要是你之前是先赋值再解绑,那行为已经在beforeSave阶段触发过了,自然没用。

方案3:测试环境下临时禁用行为

可以在模型的behaviors()方法里判断当前环境,测试环境不注册BlamemableBehavior:

use yii\behaviors\BlamemableBehavior;

class Order extends \yii\db\ActiveRecord
{
    // ...其他代码

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        
        // 非测试环境才加载BlamemableBehavior
        if (!YII_ENV_TEST) {
            $behaviors['blameable'] = [
                'class' => BlamemableBehavior::class,
                'createdByAttribute' => 'created_by',
                // 其他配置项
            ];
        }
        
        return $behaviors;
    }
}

这样测试时模型不会加载这个行为,你可以完全手动控制created_by的值。

额外检查点

  • 确认模型的rules()里给created_by加上了safe规则,确保可以手动赋值:
    public function rules()
    {
        return [
            // ...其他规则
            [['created_by'], 'integer'],
            [['created_by'], 'safe'],
        ];
    }
    
  • 检查数据库表的created_by字段,确认没有设置错误的非空约束(当然如果业务需要非空,那前面的方案必须落实)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:52:16