1
votes

I have a function I am writing that uses the Doctrine DBAL system. This uses a static function to connect as follows:

$conn = \Doctrine\DBAL\DriverManager::getConnection($connectionParams, $config);

I want to unit test this functionality with a mock.

public function openNewConnection(string $database_name): Connection
{
       try {
            // some logic where I check the validity of the connection
            $this->connection = DriverManager::getConnection($connection_params, $config);
            break;
        } catch (Exception $e) {
            // catch the different errors that could be created
        }
    return $this->connection;
}

I cannot use dependency injection as a way round this as:

  • I am dynamically generating $connectionParams : I need to make the call here
  • there is no (proper) way to non statically call this function : I would just be moving the problem elsewhere

I've been working in phpunit, and I've also had a look at mockery. I don't really see how I am meant to make this work:

This mockery test doesn't work, but I'm unsure of how it should:

public function testConnect(): void
{
    // mocked connection return
    $mocked_connection = new Connection([], $this->driver);

    // use Mockery to simulate static call
    $driver_manager = Mockery::mock('alias:\Doctrine\DBAL\DriverManager');
    $driver_manager->shouldReceive('getConnection')
                   ->once()
                   ->andReturn($mocked_connection);

    $database = new Database($this->database_configuration_file);
    $database->openNewConnection('test_db_cluster_01');

    $this->assertEquals($mocked_connection, $database->getConnection());
}

From what I can see, the $database isn't even aware of $driver_manager, so I don't see how the mocking would happen.

Here's my question:

  • Is it even possible to test a function called statically like this?
  • If so, is mockery a/the way to do this?
  • If so, what is wrong with my above test?
1
(that's not an answer) Actually, you can use dependency injection in your case. Instead of calling DriverManager::getConnection() you can use $this->connectionFactory->getConnection($connectionParams). Now you can inject (and mock in tests) the $connectionFactory. - Ivan Kalita
Nope, because the $connectionParams are not externally known. The aim of the openNewConnection function is to parse over multiple connection parameters and connect. While I could factor the "connection bit" out to a separate function, it doesn't stop the fact that the connection is still static. I want to mock the static call. - elb98rm

1 Answers

1
votes
  1. Yes, it is possible.
  2. Yes, Mockery (as well as PHPUnit itself) can do this (using "fake autoloading"). Check this article for more information.
  3. I didn't find any problems in your test. Please, check this repo. I tried to reproduce your problem, but everything goes OK.