StatementIteratorTest.php 2.99 KB
Newer Older
1 2 3 4
<?php

namespace Doctrine\Tests\DBAL\Driver;

5 6 7 8 9
use Doctrine\DBAL\Driver\IBMDB2\DB2Statement;
use Doctrine\DBAL\Driver\Mysqli\MysqliStatement;
use Doctrine\DBAL\Driver\OCI8\OCI8Statement;
use Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereStatement;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement;
10 11
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
12
use Doctrine\DBAL\Portability\Statement as PortabilityStatement;
Sergei Morozov's avatar
Sergei Morozov committed
13
use Doctrine\Tests\DbalTestCase;
14 15 16 17
use IteratorAggregate;
use PHPUnit\Framework\MockObject\MockObject;
use Traversable;
use function extension_loaded;
18

Sergei Morozov's avatar
Sergei Morozov committed
19
class StatementIteratorTest extends DbalTestCase
20
{
21 22 23 24
    /**
     * @dataProvider statementProvider()
     */
    public function testGettingIteratorDoesNotCallFetch(string $class) : void
25
    {
26 27
        /** @var IteratorAggregate|MockObject $stmt */
        $stmt = $this->createPartialMock($class, ['fetch', 'fetchAll', 'fetchColumn']);
28 29 30 31
        $stmt->expects($this->never())->method('fetch');
        $stmt->expects($this->never())->method('fetchAll');
        $stmt->expects($this->never())->method('fetchColumn');

32 33 34 35 36 37 38 39 40 41
        $stmt->getIterator();
    }

    public function testIteratorIterationCallsFetchOncePerStep() : void
    {
        $stmt = $this->createMock(Statement::class);

        $calls = 0;
        $this->configureStatement($stmt, $calls);

42
        $stmtIterator = new StatementIterator($stmt);
43 44

        $this->assertIterationCallsFetchOncePerStep($stmtIterator, $calls);
45 46
    }

47 48 49 50 51 52 53 54 55 56 57 58 59
    /**
     * @dataProvider statementProvider()
     */
    public function testStatementIterationCallsFetchOncePerStep(string $class) : void
    {
        $stmt = $this->createPartialMock($class, ['fetch']);

        $calls = 0;
        $this->configureStatement($stmt, $calls);
        $this->assertIterationCallsFetchOncePerStep($stmt, $calls);
    }

    private function configureStatement(MockObject $stmt, int &$calls) : void
60 61
    {
        $values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false, 'impossible'];
Sergei Morozov's avatar
Sergei Morozov committed
62
        $calls  = 0;
63 64 65

        $stmt->expects($this->exactly(10))
            ->method('fetch')
Sergei Morozov's avatar
Sergei Morozov committed
66
            ->willReturnCallback(static function () use ($values, &$calls) {
67 68
                $value = $values[$calls];
                $calls++;
69

70 71
                return $value;
            });
72
    }
73

74 75 76
    private function assertIterationCallsFetchOncePerStep(Traversable $iterator, int &$calls) : void
    {
        foreach ($iterator as $i => $_) {
77 78 79
            $this->assertEquals($i + 1, $calls);
        }
    }
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

    /**
     * @return string[][]
     */
    public static function statementProvider() : iterable
    {
        if (extension_loaded('ibm_db2')) {
            yield [DB2Statement::class];
        }

        yield [MysqliStatement::class];

        if (extension_loaded('oci8')) {
            yield [OCI8Statement::class];
        }

        yield [PortabilityStatement::class];
        yield [SQLAnywhereStatement::class];

        if (extension_loaded('sqlsrv')) {
            yield [SQLSrvStatement::class];
        }
    }
103
}