PHPUnit测试仅在断言前加sleep才通过,求排查原因
PHPUnit测试异常问题分析
问题描述
我有几个表现异常的PHPUnit测试:测试一直失败,但在断言前添加断点或sleep(1)就能够成功。示例代码如下:
public function test_it_confirms_time_pair() { $this->actingAs($this->authorizedUser); $this->assertNull($this->testTimeWork->confirmed_at); $this->post(route("times.confirm", $this->testTimeWork)); // sleep(1); <-- 没有此行或上方断点时,测试失败。 $this->assertNotNull($this->testTimeWork->fresh()->confirmed_at); }
后台的控制器动作仅修改了特定行的一个字段,请问该问题的成因是什么?
问题成因
- 数据库事务未及时提交:如果测试使用了事务包裹(比如Laravel默认的测试事务机制),控制器的修改操作可能还处于未提交的事务中,
fresh()直接查询数据库时,事务内的变更对外部查询不可见。断点或sleep给了事务完成提交的时间,测试就能通过。 - 数据库读写分离延迟:若系统采用读写分离架构,控制器的写操作在主库完成后,从库同步数据需要时间。
fresh()可能读取的是从库的旧数据,此时同步未完成导致断言失败;等待1秒后数据同步完成,就能读到更新后的值。 - 异步任务未执行完成:如果控制器的更新触发了异步队列任务或延迟执行的模型事件,实际修改字段的操作是异步进行的。测试代码没有等待异步任务结束就直接断言,自然失败;断点或
sleep给了异步任务执行的时间,测试因此通过。
内容的提问来源于stack exchange,提问作者TimSch
相关产品推荐
相关产品推荐

