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

如何对包含Doctrine DBAL静态调用的函数进行单元测试

如何Mock Doctrine DBAL的DriverManager静态方法进行单元测试

针对你要测试的openNewConnection方法——它依赖DriverManager::getConnection这个静态方法创建数据库连接——我们可以通过Mock静态调用的方式,避免触发真实数据库连接,专注测试方法本身的逻辑。下面分享两种常用的实现方式:

方法一:用PHPUnit自带的静态Mock(PHPUnit 9.5+)

PHPUnit从9.5版本开始支持静态方法Mock,无需额外依赖,步骤如下:

use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Connection;
use PHPUnit\Framework\TestCase;

class YourServiceTest extends TestCase
{
    public function testOpenNewConnection_Success(): void
    {
        // 1. 创建Connection的Mock,模拟成功的连接实例
        $mockConnection = $this->createMock(Connection::class);
        
        // 2. Mock DriverManager的静态getConnection方法
        $this->mockStatic(DriverManager::class)
             ->method('getConnection')
             // 可指定预期参数,用anything()匹配任意参数
             ->with($this->anything(), $this->anything())
             ->willReturn($mockConnection);
        
        // 3. 实例化业务类并调用目标方法
        $yourService = new YourService();
        $resultConnection = $yourService->openNewConnection('test_database');
        
        // 4. 断言返回的连接是我们的Mock实例
        $this->assertSame($mockConnection, $resultConnection);
    }

    public function testOpenNewConnection_ThrowsException(): void
    {
        // 1. Mock DriverManager抛出连接失败的异常
        $this->mockStatic(DriverManager::class)
             ->method('getConnection')
             ->willThrowException(new \Exception('Failed to connect'));
        
        // 2. 调用方法并验证异常处理逻辑
        $yourService = new YourService();
        $result = $yourService->openNewConnection('test_database');
        
        // 根据实际catch逻辑调整断言,比如返回null或自定义错误
        $this->assertNull($result);
    }
}

方法二:用Mockery实现静态Mock

如果你的项目使用Mockery作为Mock工具,它通过alias:前缀可以轻松Mock全局静态类:

use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Connection;
use Mockery;
use PHPUnit\Framework\TestCase;

class YourServiceTest extends TestCase
{
    // 测试后清理Mockery实例
    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }

    public function testOpenNewConnection_Success(): void
    {
        // 1. 创建Connection的Mock对象
        $mockConnection = Mockery::mock(Connection::class);
        
        // 2. Mock DriverManager的静态getConnection方法
        Mockery::mock('alias:' . DriverManager::class)
               ->shouldReceive('getConnection')
               ->once() // 验证方法被调用一次
               ->with($this->anything(), $this->anything())
               ->andReturn($mockConnection);
        
        // 3. 执行测试并断言
        $yourService = new YourService();
        $result = $yourService->openNewConnection('test_database');
        
        $this->assertSame($mockConnection, $result);
    }

    public function testOpenNewConnection_HandleConnectionFailure(): void
    {
        // Mock DriverManager抛出异常
        Mockery::mock('alias:' . DriverManager::class)
               ->shouldReceive('getConnection')
               ->once()
               ->andThrow(new \Exception('Connection error'));
        
        $yourService = new YourService();
        $result = $yourService->openNewConnection('test_database');
        
        // 根据你的catch逻辑断言结果
        $this->assertNull($result);
    }
}

额外注意事项

  • 如果$connection_params和$config是类的私有属性,建议通过构造函数注入或提供setter方法,方便测试时传入预期参数,让Mock的with()断言更精准。
  • 测试异常场景时,记得覆盖catch块内的所有逻辑(比如日志记录、错误返回),确保所有代码分支都被测试到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:00:30