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

CakePHP4 PHPUnit测试save操作丢失auto_increment id报错排查

CakePHP4控制器PHPUnit测试中save方法后id自增失效问题

问题说明

我正在使用PHPUnit进行CakePHP4控制器测试,调用save方法后id的auto_increment属性失效。该控制器在实际应用中运行正常,但测试环境下出现报错。

  • 保存前:表的id字段为自增主键,状态正常
  • 保存后:id字段的自增属性丢失,触发数据库报错

测试代码

public function testAdd(): void
{
    $this->session([
        'Auth' => [
                'id' => 1,
                'DNI_CIF' => '22175395Z',
                'name' => 'Prueba',
                'lastname' => 'Prueba Prueba',
                'username' => 'Pruebatesting',
                'password' => 'prueba',
                'email' => 'prueba@gmail.com',
                'phone' => '639087621',
                'role' => 'admin',
                'addres_id' => 1
        ]
    ]);
    $this->get('animal/add');

    $this->assertResponseOk();

    $data=[
        'id' => 1,
        'name' => 'AñadirAnimal',
        'image' => '',
        'specie' => 'dog',
        'chip' => 'no',
        'sex' => 'intact_male',
        'race' => 'cat',
        'age' => 1,
        'information' => 'Es un animal.',
        'state' => 'sick',
        'animal_shelter' => [
            'id' => 1,
            'start_date' => '2022-11-03 10:47:38',
            'end_date' => '2022-11-03 10:47:38',
            'user_id' => 1,
            'animal_id' => 1
        ]
    ];
    $this->enableCsrfToken();

    $this->post('animal/add',$data);
    $this->assertResponseOk();
}

控制器代码

public function add()
{
    $animal = $this->Animal->newEmptyEntity();
    if ($this->request->is('post')) {
        $animal = $this->Animal->patchEntity($animal, $this->request->getData());

        if(!$animal->getErrors){

            $image = $this->request->getData('image_file');
            if($image !=NULL){
                $name  = $image->getClientFilename();
            }

            if( !is_dir(WWW_ROOT.'img'.DS.'animal-img') ){
                mkdir(WWW_ROOT.'img'.DS.'animal-img',0775);
                if($name){
                    $targetPath = WWW_ROOT.'img'.DS.'animal-img'.DS.$name;

                    $image->moveTo($targetPath);
                        
                    $animal->image = 'animal-img/'.$name;
                }
            }

            if ($this->Animal->save($animal)) {
                $this->Flash->success(__('El animal se ha añadido.'));
                return $this->redirect(['action' => 'index']);
            }
        }
        $this->Flash->error(__('El animal no se ha podido añadir, por favor intentalo de nuevo'));
    }
    $allUsers = $this->getTableLocator()->get('User');

    $user = $allUsers->find('list', ['limit' => 200])->all();
    $this->set(compact('animal','user'));
}

报错信息

1) App\Test\TestCase\Controller\AnimalControllerTest::testAdd
Possibly related to PDOException: "SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value"
…
Failed asserting that 500 is between 200 and 204.

问题原因及修复方案

1. 测试数据手动传入id的冲突

测试代码中手动设置了'id' => 1,CakePHP新增记录时若传入id,会优先使用该值而非依赖自增逻辑。测试环境中可能该id已存在,或手动传入id干扰了ORM的自增序列管理,导致后续自增属性异常。生产环境用户提交不会传入id,因此无此问题。
修复:移除测试$data中的'id' => 1,让ORM自动生成自增id。

2. 控制器错误检查的语法错误

控制器中if(!$animal->getErrors)是错误写法,getErrors是方法,需调用执行:if(!$animal->getErrors())。该错误会导致即使实体验证失败,代码仍会执行到save步骤,触发数据库异常。
修复:修正控制器中的条件判断为if(!$animal->getErrors())。

3. 测试数据库事务回滚的影响

PHPUnit默认开启事务回滚,测试结束后回滚操作,但手动插入id可能导致自增计数器未被正确重置,或回滚时影响了自增属性状态。
修复:在测试方法开头重置自增序列(根据实际表名调整):

$this->Animal->query()->execute('ALTER TABLE animals AUTO_INCREMENT = 1;');

4. 测试环境表结构一致性

确认测试数据库的表结构与生产环境一致,确保id字段确实设置为自增主键。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:30:51