Skip to content

Commit 3446ea7

Browse files
committed
Add unit test classes for ConfigurationException, FileLoader, JsonLoader, PhpLoader, YamlLoader, OverwriteMerge, StrictMerge, TreeMapStorage, and AutoValidator
- Implemented ConfigurationExceptionTest to verify exception handling. - Created FileLoaderTest to ensure proper file validation. - Developed JsonLoaderTest, PhpLoaderTest, and YamlLoaderTest to test respective loaders. - Added OverwriteMergeTest and StrictMergeTest to validate merge strategies. - Introduced TreeMapStorageTest to confirm storage operations. - Established AutoValidatorTest to check configuration validation. - Ensured comprehensive coverage for all new components except ConfigurationTest.php.
1 parent f6ad1fe commit 3446ea7

File tree

10 files changed

+840
-1
lines changed

10 files changed

+840
-1
lines changed

tests/ConfigurationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use PHPUnit\Framework\MockObject\MockObject;
1818
use PHPUnit\Framework\TestCase;
1919

20-
class ConfigurationTest extends TestCase
20+
final class ConfigurationTest extends TestCase
2121
{
2222
private string $tempDir;
2323
private Configuration $configuration;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Configurator\Tests\Exception;
6+
7+
use KaririCode\Configurator\Exception\ConfigurationException;
8+
use PHPUnit\Framework\TestCase;
9+
10+
final class ConfigurationExceptionTest extends TestCase
11+
{
12+
public function testConfigurationExceptionCanBeThrown(): void
13+
{
14+
$message = 'Test exception message';
15+
try {
16+
throw new ConfigurationException($message);
17+
} catch (ConfigurationException $e) {
18+
$this->assertInstanceOf(ConfigurationException::class, $e);
19+
$this->assertEquals($message, $e->getMessage());
20+
21+
return;
22+
}
23+
24+
$this->fail('ConfigurationException was not thrown.');
25+
}
26+
}

tests/Loader/FileLoaderTest.php

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Configurator\Tests\Loader;
6+
7+
use KaririCode\Configurator\Exception\ConfigurationException;
8+
use KaririCode\Configurator\Loader\FileLoader;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class FileLoaderTest extends TestCase
12+
{
13+
private string $tempDir;
14+
15+
protected function setUp(): void
16+
{
17+
parent::setUp();
18+
$this->tempDir = sys_get_temp_dir() . '/file_loader_test_' . uniqid();
19+
if (!mkdir($this->tempDir) && !is_dir($this->tempDir)) {
20+
throw new \RuntimeException(sprintf('Directory "%s" could not be created', $this->tempDir));
21+
}
22+
}
23+
24+
protected function tearDown(): void
25+
{
26+
parent::tearDown();
27+
$this->deleteDirectory($this->tempDir);
28+
}
29+
30+
private function deleteDirectory(string $dir): void
31+
{
32+
if (!is_dir($dir)) {
33+
return;
34+
}
35+
foreach (scandir($dir) as $item) {
36+
if ('.' === $item || '..' === $item) {
37+
continue;
38+
}
39+
$path = $dir . DIRECTORY_SEPARATOR . $item;
40+
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
41+
}
42+
rmdir($dir);
43+
}
44+
45+
private function createFile(string $filename, string $content): string
46+
{
47+
$filePath = $this->tempDir . DIRECTORY_SEPARATOR . $filename;
48+
file_put_contents($filePath, $content);
49+
50+
return $filePath;
51+
}
52+
53+
/**
54+
* A concrete subclass of FileLoader for testing purposes.
55+
*/
56+
private function createConcreteFileLoader(): FileLoader
57+
{
58+
return new class extends FileLoader {
59+
public function load(string $path): array
60+
{
61+
$this->validateFile($path);
62+
63+
// For testing, simply return an empty array
64+
return [];
65+
}
66+
67+
public function getTypes(): array
68+
{
69+
return ['test'];
70+
}
71+
};
72+
}
73+
74+
public function testValidateFileThrowsExceptionForNonExistentFile(): void
75+
{
76+
$loader = $this->createConcreteFileLoader();
77+
$filePath = $this->tempDir . '/non_existent.test';
78+
79+
$this->expectException(ConfigurationException::class);
80+
$this->expectExceptionMessage("Configuration file not found: {$filePath}");
81+
82+
$loader->load($filePath);
83+
}
84+
85+
public function testValidateFileThrowsExceptionForUnreadableFile(): void
86+
{
87+
$loader = $this->createConcreteFileLoader();
88+
$filePath = $this->createFile('unreadable.test', 'content');
89+
chmod($filePath, 0000); // Make the file unreadable
90+
91+
$this->expectException(ConfigurationException::class);
92+
$this->expectExceptionMessage("Configuration file is not readable: {$filePath}");
93+
94+
$loader->load($filePath);
95+
}
96+
97+
public function testValidateFileSucceedsForReadableFile(): void
98+
{
99+
$loader = $this->createConcreteFileLoader();
100+
$filePath = $this->createFile('readable.test', 'content');
101+
102+
// Should not throw any exception
103+
$result = $loader->load($filePath);
104+
105+
$this->assertIsArray($result);
106+
$this->assertEmpty($result);
107+
}
108+
}

tests/Loader/JsonLoaderTest.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Configurator\Tests\Loader;
6+
7+
use KaririCode\Configurator\Exception\ConfigurationException;
8+
use KaririCode\Configurator\Loader\JsonLoader;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class JsonLoaderTest extends TestCase
12+
{
13+
private string $tempDir;
14+
private JsonLoader $jsonLoader;
15+
16+
protected function setUp(): void
17+
{
18+
parent::setUp();
19+
$this->tempDir = sys_get_temp_dir() . '/json_loader_test_' . uniqid();
20+
if (!mkdir($this->tempDir) && !is_dir($this->tempDir)) {
21+
throw new \RuntimeException(sprintf('Directory "%s" could not be created', $this->tempDir));
22+
}
23+
$this->jsonLoader = new JsonLoader();
24+
}
25+
26+
protected function tearDown(): void
27+
{
28+
parent::tearDown();
29+
$this->deleteDirectory($this->tempDir);
30+
}
31+
32+
private function deleteDirectory(string $dir): void
33+
{
34+
if (!is_dir($dir)) {
35+
return;
36+
}
37+
foreach (scandir($dir) as $item) {
38+
if ('.' === $item || '..' === $item) {
39+
continue;
40+
}
41+
$path = $dir . DIRECTORY_SEPARATOR . $item;
42+
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
43+
}
44+
rmdir($dir);
45+
}
46+
47+
private function createFile(string $filename, string $content): string
48+
{
49+
$filePath = $this->tempDir . DIRECTORY_SEPARATOR . $filename;
50+
file_put_contents($filePath, $content);
51+
52+
return $filePath;
53+
}
54+
55+
public function testLoadValidJsonFile(): void
56+
{
57+
$jsonContent = json_encode([
58+
'key1' => 'value1',
59+
'key2' => 123,
60+
'key3' => true,
61+
]);
62+
$filePath = $this->createFile('valid.json', $jsonContent);
63+
64+
$result = $this->jsonLoader->load($filePath);
65+
66+
$this->assertIsArray($result);
67+
$this->assertEquals([
68+
'key1' => 'value1',
69+
'key2' => 123,
70+
'key3' => true,
71+
], $result);
72+
}
73+
74+
public function testLoadInvalidJsonFileThrowsException(): void
75+
{
76+
$invalidJsonContent = '{"key1": "value1", "key2": 123,,,}';
77+
$filePath = $this->createFile('invalid.json', $invalidJsonContent);
78+
79+
$this->expectException(ConfigurationException::class);
80+
$this->expectExceptionMessage('Failed to parse JSON file');
81+
82+
$this->jsonLoader->load($filePath);
83+
}
84+
85+
public function testLoadNonExistentFileThrowsException(): void
86+
{
87+
$filePath = $this->tempDir . '/non_existent.json';
88+
89+
$this->expectException(ConfigurationException::class);
90+
$this->expectExceptionMessage("Configuration file not found: {$filePath}");
91+
92+
$this->jsonLoader->load($filePath);
93+
}
94+
95+
public function testLoadPhpFileThatDoesNotReturnArrayThrowsException(): void
96+
{
97+
// Create a PHP file that returns a string instead of an array
98+
$phpContent = <<<'PHP'
99+
<?php
100+
return "not_an_array";
101+
PHP;
102+
$filePath = $this->createFile('not_array.json', $phpContent);
103+
104+
// Rename to .json to mimic misnamed file
105+
rename($filePath, $this->tempDir . '/not_array.json');
106+
107+
$this->expectException(ConfigurationException::class);
108+
$this->expectExceptionMessage('Failed to parse JSON file');
109+
110+
$this->jsonLoader->load($this->tempDir . '/not_array.json');
111+
}
112+
113+
public function testGetTypes(): void
114+
{
115+
$types = $this->jsonLoader->getTypes();
116+
$this->assertIsArray($types);
117+
$this->assertEquals(['json'], $types);
118+
}
119+
}

tests/Loader/PhpLoaderTest.php

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace KaririCode\Configurator\Tests\Loader;
6+
7+
use KaririCode\Configurator\Exception\ConfigurationException;
8+
use KaririCode\Configurator\Loader\PhpLoader;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class PhpLoaderTest extends TestCase
12+
{
13+
private string $tempDir;
14+
private PhpLoader $phpLoader;
15+
16+
protected function setUp(): void
17+
{
18+
parent::setUp();
19+
$this->tempDir = sys_get_temp_dir() . '/php_loader_test_' . uniqid();
20+
if (!mkdir($this->tempDir) && !is_dir($this->tempDir)) {
21+
throw new \RuntimeException(sprintf('Directory "%s" could not be created', $this->tempDir));
22+
}
23+
$this->phpLoader = new PhpLoader();
24+
}
25+
26+
protected function tearDown(): void
27+
{
28+
parent::tearDown();
29+
$this->deleteDirectory($this->tempDir);
30+
}
31+
32+
private function deleteDirectory(string $dir): void
33+
{
34+
if (!is_dir($dir)) {
35+
return;
36+
}
37+
foreach (scandir($dir) as $item) {
38+
if ('.' === $item || '..' === $item) {
39+
continue;
40+
}
41+
$path = $dir . DIRECTORY_SEPARATOR . $item;
42+
is_dir($path) ? $this->deleteDirectory($path) : unlink($path);
43+
}
44+
rmdir($dir);
45+
}
46+
47+
private function createFile(string $filename, string $content): string
48+
{
49+
$filePath = $this->tempDir . DIRECTORY_SEPARATOR . $filename;
50+
file_put_contents($filePath, $content);
51+
52+
return $filePath;
53+
}
54+
55+
public function testLoadValidPhpFile(): void
56+
{
57+
$phpContent = <<<'PHP'
58+
<?php
59+
return [
60+
'key1' => 'value1',
61+
'key2' => 123,
62+
'key3' => true,
63+
];
64+
PHP;
65+
$filePath = $this->createFile('valid.php', $phpContent);
66+
67+
$result = $this->phpLoader->load($filePath);
68+
69+
$this->assertIsArray($result);
70+
$this->assertEquals([
71+
'key1' => 'value1',
72+
'key2' => 123,
73+
'key3' => true,
74+
], $result);
75+
}
76+
77+
public function testLoadPhpFileThatDoesNotReturnArrayThrowsException(): void
78+
{
79+
$phpContent = <<<'PHP'
80+
<?php
81+
return "not_an_array";
82+
PHP;
83+
$filePath = $this->createFile('not_array.php', $phpContent);
84+
85+
$this->expectException(ConfigurationException::class);
86+
$this->expectExceptionMessage('PHP configuration file must return an array');
87+
88+
$this->phpLoader->load($filePath);
89+
}
90+
91+
public function testLoadNonExistentFileThrowsException(): void
92+
{
93+
$filePath = $this->tempDir . '/non_existent.php';
94+
95+
$this->expectException(ConfigurationException::class);
96+
$this->expectExceptionMessage("Configuration file not found: {$filePath}");
97+
98+
$this->phpLoader->load($filePath);
99+
}
100+
101+
// public function testLoadPhpFileWithSyntaxErrorThrowsException(): void
102+
// {
103+
// $phpContent = <<<'PHP'
104+
// <?php
105+
// return [
106+
// 'key1' => 'value1',
107+
// 'key2' => 123,
108+
// // Missing closing bracket
109+
// PHP;
110+
// $filePath = $this->createFile('syntax_error.php', $phpContent);
111+
112+
// $this->expectException(ConfigurationException::class);
113+
// $this->expectExceptionMessage('Failed to parse PHP file');
114+
115+
// $this->phpLoader->load($filePath);
116+
// }
117+
118+
public function testGetTypes(): void
119+
{
120+
$types = $this->phpLoader->getTypes();
121+
$this->assertIsArray($types);
122+
$this->assertEquals(['php'], $types);
123+
}
124+
}

0 commit comments

Comments
 (0)