Skip to content

Commit da1db3a

Browse files
Merge pull request #220 from mirko-pagliai/2.15.x-dev
Improved `SqliteExecutorTest` by refining schema collection mock and …
2 parents e54f908 + 8301b9f commit da1db3a

File tree

15 files changed

+375
-487
lines changed

15 files changed

+375
-487
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
4242
- name: Setup PostgreSQL latest
4343
if: matrix.db-type == 'pgsql'
44-
run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=test -p 5432:5432 -d postgres:9.6
44+
run: docker run --rm --name=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=test -p 5432:5432 -d postgres:11.16
4545

4646
- uses: actions/checkout@v4
4747

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# 2.x branch
22
## 2.15 branch
3+
### 2.15.3
4+
* slightly improved the `SqliteExecutorTest` test class;
5+
* refactor tests to replace deprecated PHPUnit mocks with stubs and improve event-based tests;
6+
* PostgreSQL 11.16 is used by default for testing.
7+
38
### 2.15.2
49
* the `Plugin` class has been deprecated and will be removed in a future release, use `DatabaseBackupPlugin` instead;
510
* full support for PHP 8.5. CI actions have been optimized.

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"cakephp/cakephp-codesniffer": "^5.0",
2424
"cakedc/cakephp-phpstan": "^4.0",
2525
"cakephp/migrations": "^4.0",
26-
"phpunit/phpunit": "^10.5.5 || ^11.1.3"
26+
"phpunit/phpunit": "^10.5.5 || ^11.1.3 || ^12.0.9"
2727
},
2828
"autoload": {
2929
"psr-4": {

composer.lock

Lines changed: 227 additions & 321 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Console/Command.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929

3030
/**
3131
* Base class for console commands.
32+
*
33+
* @extends \Cake\Console\BaseCommand<\Cake\Command\Command>
3234
*/
3335
abstract class Command extends BaseCommand
3436
{

src/Executor/SqliteExecutor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function beforeImport(EventInterface $Event)
5858
//For each table, drops the table
5959
$this->dropAllTables();
6060

61-
//Needs disconnect and re-connect because the database schema has changed
61+
//Needs to disconnect and to re-connect, because the database schema has changed
6262
$Connection->getDriver()->disconnect();
6363
$Connection->getDriver()->connect();
6464
}

tests/TestCase/Command/ExportCommandTest.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,20 @@ public function testExecuteNotWritableTarget(): void
8181
$this->assertErrorContains('File or directory `/noExistingDir` is not writable');
8282
}
8383

84-
/**
85-
* @throws \PHPUnit\Framework\MockObject\Exception
86-
*/
8784
#[Test]
8885
public function testExecuteOnStoppedEvent(): void
8986
{
90-
$ExportCommand = $this->createPartialMock(ExportCommand::class, ['getBackupExport']);
91-
92-
$ExportCommand
93-
->expects($this->once())
94-
->method('getBackupExport')
95-
->willReturn($this->createConfiguredMock(BackupExport::class, ['export' => false]));
87+
$ExportCommand = new class extends ExportCommand {
88+
public function getBackupExport(): BackupExport
89+
{
90+
return new class extends BackupExport {
91+
public function export(): string|false
92+
{
93+
return false;
94+
}
95+
};
96+
}
97+
};
9698

9799
$this->expectException(StopException::class);
98100
$this->expectExceptionMessage('The `Backup.beforeExport` event stopped the operation');

tests/TestCase/Command/ImportCommandTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ public function testExecuteNoExistingFile(): void
7171

7272
/**
7373
* Test for `execute()` method, with `--timeout` option.
74-
*
75-
* @throws \PHPUnit\Framework\MockObject\Exception
7674
*/
7775
#[Test]
7876
public function testExecuteTimeoutOption(): void
@@ -115,18 +113,20 @@ public function testExecuteTimeoutOption(): void
115113
$this->assertErrorEmpty();
116114
}
117115

118-
/**
119-
* @throws \PHPUnit\Framework\MockObject\Exception
120-
*/
121116
#[Test]
122117
public function testExecuteOnStoppedEvent(): void
123118
{
124-
$ImportCommand = $this->createPartialMock(ImportCommand::class, ['getBackupImport']);
125-
126-
$ImportCommand
127-
->expects($this->once())
128-
->method('getBackupImport')
129-
->willReturn($this->createConfiguredMock(BackupImport::class, ['import' => false]));
119+
$ImportCommand = new class extends ImportCommand {
120+
public function getBackupImport(): BackupImport
121+
{
122+
return new class extends BackupImport {
123+
public function import(): string|false
124+
{
125+
return false;
126+
}
127+
};
128+
}
129+
};
130130

131131
$this->expectException(StopException::class);
132132
$this->expectExceptionMessage('The `Backup.beforeImport` event stopped the operation');

tests/TestCase/Executor/AbstractExecutorTest.php

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,16 @@
3232
#[CoversClass(AbstractExecutor::class)]
3333
class AbstractExecutorTest extends TestCase
3434
{
35-
/**
36-
* @var \Cake\Datasource\ConnectionInterface&\PHPUnit\Framework\MockObject\MockObject
37-
*/
38-
protected ConnectionInterface $Connection;
39-
4035
protected AbstractExecutor $Executor;
4136

4237
/**
43-
* {@inheritDoc}
44-
*
45-
* @throws \PHPUnit\Framework\MockObject\Exception
38+
* @inheritDoc
4639
*/
4740
protected function setUp(): void
4841
{
49-
$this->Connection = $this->createMock(ConnectionInterface::class);
42+
$Connection = $this->createStub(ConnectionInterface::class);
5043

51-
$this->Executor = new class ($this->Connection) extends AbstractExecutor {
44+
$this->Executor = new class ($Connection) extends AbstractExecutor {
5245
};
5346
}
5447

@@ -64,7 +57,6 @@ protected function setUp(): void
6457
public function testCallMagicMethod(string $expectedNewMethod, string $oldMethod): void
6558
{
6659
$Executor = $this->createPartialMock(AbstractExecutor::class, [$expectedNewMethod]);
67-
6860
$Executor
6961
->expects($this->once())
7062
->method($expectedNewMethod)
@@ -97,22 +89,19 @@ public function testImplementedEvents(): void
9789
#[TestWith(['\'sqlite3-binary\' my-database .dump | \'bzip2-binary\' > \'filename.sql.bz2\'', 'filename.sql.bz2'])]
9890
public function testGetExportCommand(string $expectedExportCommand, string $filename): void
9991
{
100-
$Executor = $this->getMockBuilder(AbstractExecutor::class)
101-
->setConstructorArgs([$this->Connection, 'Sqlite'])
102-
->onlyMethods(['getBinary', 'getConfig'])
103-
->getMock();
92+
$Connection = $this->createStub(ConnectionInterface::class);
10493

105-
$Executor
106-
->expects($this->any())
107-
->method('getBinary')
108-
->willReturnCallback(function (Compression|string $binaryName): string {
94+
$Executor = new class ($Connection, 'Sqlite') extends AbstractExecutor {
95+
public function getBinary(string|Compression $binaryName): string
96+
{
10997
return ($binaryName instanceof Compression ? strtolower($binaryName->name) : $binaryName) . '-binary';
110-
});
98+
}
11199

112-
$Executor
113-
->expects($this->any())
114-
->method('getConfig')
115-
->willReturnCallback(fn(string $key): string => 'my-' . $key);
100+
public function getConfig(string $key): string
101+
{
102+
return 'my-' . $key;
103+
}
104+
};
116105

117106
$result = $Executor->getExportCommand($filename);
118107

@@ -128,22 +117,19 @@ public function testGetExportCommand(string $expectedExportCommand, string $file
128117
#[TestWith(['\'bzip2-binary\' -dc \'filename.sql.bz2\' | \'sqlite3-binary\' my-database', 'filename.sql.bz2'])]
129118
public function testGetImportCommand(string $expectedImportCommand, string $filename): void
130119
{
131-
$Executor = $this->getMockBuilder(AbstractExecutor::class)
132-
->setConstructorArgs([$this->Connection, 'Sqlite'])
133-
->onlyMethods(['getBinary', 'getConfig'])
134-
->getMock();
120+
$Connection = $this->createStub(ConnectionInterface::class);
135121

136-
$Executor
137-
->expects($this->any())
138-
->method('getBinary')
139-
->willReturnCallback(function (Compression|string $binaryName): string {
122+
$Executor = new class ($Connection, 'Sqlite') extends AbstractExecutor {
123+
public function getBinary(string|Compression $binaryName): string
124+
{
140125
return ($binaryName instanceof Compression ? strtolower($binaryName->name) : $binaryName) . '-binary';
141-
});
126+
}
142127

143-
$Executor
144-
->expects($this->any())
145-
->method('getConfig')
146-
->willReturnCallback(fn(string $key): string => 'my-' . $key);
128+
public function getConfig(string $key): string
129+
{
130+
return 'my-' . $key;
131+
}
132+
};
147133

148134
$result = $Executor->getImportCommand($filename);
149135

@@ -175,12 +161,16 @@ public function testGetBinaryNoExistingBinary(string $expectedBinaryName, string
175161
#[TestWith([null, 'noExisting'])]
176162
public function testGetConfig(?string $expectedConfig, string $configKey): void
177163
{
178-
$this->Connection
164+
$Connection = $this->createMock(ConnectionInterface::class);
165+
$Connection
179166
->expects($this->once())
180167
->method('config')
181168
->willReturn(['name' => 'test']);
182169

183-
$result = $this->Executor->getConfig($configKey);
170+
$Executor = new class ($Connection) extends AbstractExecutor {
171+
};
172+
173+
$result = $Executor->getConfig($configKey);
184174
$this->assertSame($expectedConfig, $result);
185175
}
186176
}

tests/TestCase/Executor/SqliteExecutorTest.php

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717

1818
use Cake\Database\Connection;
1919
use Cake\Database\Driver\Sqlite;
20-
use Cake\Database\Schema\CollectionInterface;
20+
use Cake\Database\Schema\Collection as SchemaCollection;
2121
use Cake\Database\Schema\TableSchema;
22+
use Cake\Database\Schema\TableSchemaInterface;
2223
use Cake\Database\StatementInterface;
2324
use Cake\Datasource\ConnectionInterface;
2425
use DatabaseBackup\Executor\AbstractExecutor;
@@ -36,55 +37,45 @@
3637
class SqliteExecutorTest extends TestCase
3738
{
3839
/**
40+
* @link \DatabaseBackup\Executor\SqliteExecutor::dropAllTables()
3941
* @throws \PHPUnit\Framework\MockObject\Exception
4042
*/
4143
#[Test]
4244
public function testDropAllTables(): void
4345
{
4446
$tables = [1 => 'articles', 2 => 'comments'];
4547

48+
$Connection = $this->getMockBuilder(Connection::class)
49+
->setConstructorArgs([['driver' => new Sqlite()]])
50+
->onlyMethods(['execute'])
51+
->getMock();
52+
4653
/**
47-
* `$Schema` describes the tables.
54+
* `$SchemaCollection` describes the tables.
4855
*/
49-
$Schema = $this->createMock(CollectionInterface::class);
56+
$SchemaCollection = new class ($Connection) extends SchemaCollection {
57+
public function describe(string $name, array $options = []): TableSchemaInterface
58+
{
59+
return new TableSchema($name);
60+
}
5061

51-
$Schema
52-
->expects($this->once())
53-
->method('listTables')
54-
->willReturn($tables);
55-
56-
$Schema
57-
->expects($this->any())
58-
->method('describe')
59-
->willReturnCallback(function (string $tableName): TableSchema {
60-
return $this->getMockBuilder(TableSchema::class)
61-
->setConstructorArgs([$tableName])
62-
->onlyMethods([])
63-
->getMock();
64-
});
62+
public function listTables(): array
63+
{
64+
return [1 => 'articles', 2 => 'comments'];
65+
}
66+
};
6567

66-
$Connection = $this->createMock(Connection::class);
67-
68-
$Connection
69-
->expects($this->any())
70-
->method('getDriver')
71-
->willReturn(new Sqlite());
72-
73-
$Connection
74-
->expects($this->once())
75-
->method('getSchemaCollection')
76-
->willReturn($Schema);
68+
$Connection->setSchemaCollection($SchemaCollection);
7769

7870
/**
7971
* The important thing is to check the number of times and the arguments with which the `Connection::execute()`
8072
* method is called.
8173
*/
8274
$matcher = $this->exactly(2);
83-
$Connection
84-
->expects($matcher)
75+
$Connection->expects($matcher)
8576
->method('execute')
8677
->willReturnCallback(function (string $sql) use ($matcher, $tables): StatementInterface {
87-
$expectedSql = sprintf('DROP TABLE "%s"', $tables[$matcher->numberOfInvocations()]);
78+
$expectedSql = "DROP TABLE \"{$tables[$matcher->numberOfInvocations()]}\"";
8879
$this->assertSame($expectedSql, $sql);
8980

9081
return $this->createStub(StatementInterface::class);
@@ -95,6 +86,7 @@ public function testDropAllTables(): void
9586
}
9687

9788
/**
89+
* @link \DatabaseBackup\Executor\SqliteExecutor::beforeImport()
9890
* @throws \PHPUnit\Framework\MockObject\Exception
9991
*/
10092
#[Test]

0 commit comments

Comments
 (0)