RunSqlCommandTest.php 4.25 KB
Newer Older
1 2
<?php

3
namespace Doctrine\DBAL\Tests\Tools\Console;
4

Sergei Morozov's avatar
Sergei Morozov committed
5
use Doctrine\DBAL\Connection;
6 7
use Doctrine\DBAL\Tools\Console\Command\RunSqlCommand;
use Doctrine\DBAL\Tools\Console\ConsoleRunner;
Sergei Morozov's avatar
Sergei Morozov committed
8
use LogicException;
Grégoire Paris's avatar
Grégoire Paris committed
9
use PHPUnit\Framework\MockObject\MockObject;
Sergei Morozov's avatar
Sergei Morozov committed
10 11
use PHPUnit\Framework\TestCase;
use RuntimeException;
12 13 14
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Tester\CommandTester;

Sergei Morozov's avatar
Sergei Morozov committed
15
class RunSqlCommandTest extends TestCase
16 17 18 19 20 21
{
    /** @var CommandTester */
    private $commandTester;
    /** @var RunSqlCommand */
    private $command;

Grégoire Paris's avatar
Grégoire Paris committed
22
    /** @var Connection&MockObject */
23 24
    private $connectionMock;

25
    protected function setUp() : void
26 27 28 29
    {
        $application = new Application();
        $application->add(new RunSqlCommand());

Sergei Morozov's avatar
Sergei Morozov committed
30
        $this->command       = $application->find('dbal:run-sql');
31 32
        $this->commandTester = new CommandTester($this->command);

Sergei Morozov's avatar
Sergei Morozov committed
33
        $this->connectionMock = $this->createMock(Connection::class);
34
        $this->connectionMock->method('fetchAllAssociative')
Sergei Morozov's avatar
Sergei Morozov committed
35
            ->willReturn([[1]]);
36 37 38 39 40 41 42
        $this->connectionMock->method('executeUpdate')
            ->willReturn(42);

        $helperSet = ConsoleRunner::createHelperSet($this->connectionMock);
        $this->command->setHelperSet($helperSet);
    }

43
    public function testMissingSqlArgument() : void
44 45
    {
        try {
Sergei Morozov's avatar
Sergei Morozov committed
46
            $this->commandTester->execute([
47 48
                'command' => $this->command->getName(),
                'sql' => null,
Sergei Morozov's avatar
Sergei Morozov committed
49
            ]);
50
            self::fail('Expected a runtime exception when omitting sql argument');
Sergei Morozov's avatar
Sergei Morozov committed
51
        } catch (RuntimeException $e) {
52
            self::assertStringContainsString("Argument 'SQL", $e->getMessage());
53 54 55
        }
    }

56
    public function testIncorrectDepthOption() : void
57 58
    {
        try {
Sergei Morozov's avatar
Sergei Morozov committed
59
            $this->commandTester->execute([
60 61 62
                'command' => $this->command->getName(),
                'sql' => 'SELECT 1',
                '--depth' => 'string',
Sergei Morozov's avatar
Sergei Morozov committed
63
            ]);
64
            self::fail('Expected a logic exception when executing with a stringy depth');
Sergei Morozov's avatar
Sergei Morozov committed
65
        } catch (LogicException $e) {
66
            self::assertStringContainsString("Option 'depth'", $e->getMessage());
67 68 69
        }
    }

70
    public function testSelectStatementsPrintsResult() : void
71
    {
72
        $this->expectConnectionFetchAllAssociative();
73

74
        $exitCode = $this->commandTester->execute([
75 76
            'command' => $this->command->getName(),
            'sql' => 'SELECT 1',
Sergei Morozov's avatar
Sergei Morozov committed
77
        ]);
78
        self::assertSame(0, $exitCode);
79

80 81
        self::assertMatchesRegularExpression('@int.*1.*@', $this->commandTester->getDisplay());
        self::assertMatchesRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
82 83
    }

84
    public function testUpdateStatementsPrintsAffectedLines() : void
85 86 87
    {
        $this->expectConnectionExecuteUpdate();

Sergei Morozov's avatar
Sergei Morozov committed
88
        $this->commandTester->execute([
89 90
            'command' => $this->command->getName(),
            'sql' => 'UPDATE foo SET bar = 42',
Sergei Morozov's avatar
Sergei Morozov committed
91
        ]);
92

93 94
        self::assertMatchesRegularExpression('@int.*42.*@', $this->commandTester->getDisplay());
        self::assertDoesNotMatchRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
95 96
    }

97
    private function expectConnectionExecuteUpdate() : void
98 99
    {
        $this->connectionMock
100
            ->expects(self::exactly(1))
101 102
            ->method('executeUpdate');
        $this->connectionMock
103
            ->expects(self::exactly(0))
104
            ->method('fetchAllAssociative');
105 106
    }

107
    private function expectConnectionFetchAllAssociative() : void
108 109
    {
        $this->connectionMock
110
            ->expects(self::exactly(0))
111 112
            ->method('executeUpdate');
        $this->connectionMock
113
            ->expects(self::exactly(1))
114
            ->method('fetchAllAssociative');
115
    }
116

117
    public function testStatementsWithFetchResultPrintsResult() : void
118
    {
119
        $this->expectConnectionFetchAllAssociative();
120

Sergei Morozov's avatar
Sergei Morozov committed
121
        $this->commandTester->execute([
122 123
            'command' => $this->command->getName(),
            'sql' => '"WITH bar as (SELECT 1) SELECT * FROM bar',
124
            '--force-fetch' => true,
Sergei Morozov's avatar
Sergei Morozov committed
125
        ]);
126

127 128
        self::assertMatchesRegularExpression('@int.*1.*@', $this->commandTester->getDisplay());
        self::assertMatchesRegularExpression('@array.*1.*@', $this->commandTester->getDisplay());
129
    }
130
}