使用Codeception测试Yii2应用时,Fixtures引发“连接过多”错误如何解决?
解决Codeception+Yii2 Fixtures引发的“too many connections”问题
兄弟,我之前也踩过这个坑!你现在手动在每个测试方法里调用loadFixture()和unLoadFixture()的方式,很容易导致数据库连接没被正确回收——尤其是如果某个测试抛出异常,unLoadFixture()可能根本没机会执行,连接就一直挂着,积累多了就爆错。
下面给你几个靠谱的解决办法:
推荐:让框架自动管理Fixture生命周期
别再手动加载卸载了!直接在测试类里声明fixtures配置,Codeception和Yii2会自动在每个测试前加载Fixture,测试完成后清理并关闭连接:
class ServiceTest extends \Codeception\Test\Unit { protected $tester; // 在这里声明需要的Fixture,框架自动处理加载/卸载 protected function _fixtures() { return [ 'user' => ['class' => UserFixture::class], ]; } // 测试前的初始化逻辑写在这里(可选) protected function _before() { // 比如设置一些全局测试数据,不需要手动碰Fixture加载 } // 测试后的清理逻辑写在这里(可选) protected function _after() { // 框架会自动处理Fixture的资源释放,除非你有额外自定义资源要清理 } public function testSuccessSignin() { // 直接用Fixture的数据就行,不用手动加载 $testUser = $this->tester->grabFixture('user')->getModel(); $form = new SigninForm([ 'email' => $testUser->email, // 其他表单参数 ]); // ...你的测试逻辑 } }
特殊情况:必须手动管理Fixture的处理
如果因为业务特殊性,一定要手动加载Fixture,那必须保证无论测试成功还是失败,连接都能被关闭,用try-finally块兜底:
public function testSuccessSignin() { try { $this->loadFixture(); // ...你的测试逻辑代码 } finally { // 不管测试有没有报错,都会执行这里的关闭操作 $this->unLoadFixture(); } }
另外还要检查你的UserFixture类,确保它继承了Yii2的\yii\test\Fixture基类——这个基类已经帮你处理了数据库连接的生命周期,大部分情况下根本不需要你手动调用db->close()。如果你的Fixture自定义了init()或者afterLoad()方法,记得一定要调用父类的对应方法哦。
额外优化小建议
- 可以检查下数据库的
max_connections配置,不过测试环境默认值一般足够,主要问题还是连接没被正确回收; - 确保你的Yii2数据库组件配置里开启了连接管理,Yii2默认的
db组件已经有连接池机制,能自动复用和回收连接。
内容的提问来源于stack exchange,提问作者Mik
相关产品推荐
相关产品推荐

