-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Split tests into files testing individual components - Added test doubles for component independence - Redesigned fixture example classes
- Loading branch information
Showing
21 changed files
with
1,182 additions
and
656 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Polymorphine/Container package. | ||
* | ||
* (c) Shudd3r <q3.shudder@gmail.com> | ||
* | ||
* This source file is subject to the MIT license that is bundled | ||
* with this source code in the file LICENSE. | ||
*/ | ||
|
||
namespace Polymorphine\Container\Tests; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Polymorphine\Container\CompositeContainer; | ||
use Polymorphine\Container\Records; | ||
use Psr\Container\ContainerInterface; | ||
use Psr\Container\NotFoundExceptionInterface; | ||
|
||
|
||
class CompositeContainerTest extends TestCase | ||
{ | ||
public function testInstantiation() | ||
{ | ||
$this->assertInstanceOf(ContainerInterface::class, $this->container()); | ||
} | ||
|
||
public function testContainer_getRecordId_ReturnsRecordValue() | ||
{ | ||
$container = $this->container(['foo' => Doubles\MockedRecord::new('fooValue')]); | ||
$this->assertSame('fooValue', $container->get('foo')); | ||
} | ||
|
||
public function testContainer_getContainerId_ReturnsSubContainer() | ||
{ | ||
$subContainer = Doubles\FakeContainer::new(); | ||
$container = $this->container(['foo' => Doubles\MockedRecord::new('fooValue')], ['sub' => $subContainer]); | ||
$this->assertSame($subContainer, $container->get('sub')); | ||
} | ||
|
||
public function testContainer_getWithContainerPrefixedId_ReturnsSubContainerValue() | ||
{ | ||
$subContainer = Doubles\FakeContainer::new(['foo' => 'subFooValue']); | ||
$container = $this->container(['foo' => Doubles\MockedRecord::new('fooValue')], ['sub' => $subContainer]); | ||
$this->assertSame('subFooValue', $container->get('sub.foo')); | ||
} | ||
|
||
public function testContainerWithOverlappingEntries_getWithConflictedId_ReturnsValueFromContainer() | ||
{ | ||
$subContainer = Doubles\FakeContainer::new(['bar' => 'subFooValue']); | ||
$container = $this->container(['foo' => Doubles\MockedRecord::new('inaccessible')], ['foo' => $subContainer]); | ||
$this->assertSame($subContainer, $container->get('foo')); | ||
|
||
$container = $this->container(['foo.bar' => Doubles\MockedRecord::new('inaccessible')], ['foo' => $subContainer]); | ||
$this->assertSame('subFooValue', $container->get('foo.bar')); | ||
} | ||
|
||
public function testContainer_has_ReturnsIfEntryIsDefinedAndAccessible() | ||
{ | ||
$container = $this->container([ | ||
'foo.something' => Doubles\MockedRecord::new('inaccessible'), | ||
'bar.something' => Doubles\MockedRecord::new(null) | ||
], [ | ||
'foo' => Doubles\FakeContainer::new(['bar' => null, 'baz' => 0]) | ||
]); | ||
|
||
$this->assertFalse($container->has('foo.something')); | ||
$this->assertTrue($container->has('bar.something')); | ||
$this->assertTrue($container->has('foo.bar')); | ||
$this->assertTrue($container->has('foo.baz')); | ||
$this->assertTrue($container->has('foo')); | ||
$this->assertFalse($container->has('bar')); | ||
} | ||
|
||
/** | ||
* @dataProvider undefinedEntries | ||
* | ||
* @param string $id | ||
*/ | ||
public function testContainer_getForUndefinedEntry_ThrowsException(string $id) | ||
{ | ||
$container = $this->container([ | ||
'foo.something' => Doubles\MockedRecord::new('inaccessible'), | ||
'foo.another' => Doubles\MockedRecord::new('inaccessible'), | ||
'bar.something' => Doubles\MockedRecord::new(null) | ||
], [ | ||
'foo' => Doubles\FakeContainer::new(['bar' => null, 'baz' => 0]) | ||
]); | ||
|
||
$this->expectException(NotFoundExceptionInterface::class); | ||
$container->get($id); | ||
} | ||
|
||
public function undefinedEntries() | ||
{ | ||
return [['foo.something'], ['bar'], ['foo.another'], ['bar.something.else']]; | ||
} | ||
|
||
public function testContainer_getEntryWithReferencesToContainer_ReturnsResolvedValue() | ||
{ | ||
$container = $this->container([ | ||
'foo' => Doubles\MockedRecord::new(function (ContainerInterface $c) { | ||
$function = $c->get('bar'); | ||
return $function($c->get('sub.foo')); | ||
}), | ||
'bar' => Doubles\MockedRecord::new(function (ContainerInterface $c) { | ||
return function (string $foo) use ($c) { return $foo . ' + ' . $c->get('sub.bar'); }; | ||
}) | ||
], [ | ||
'sub' => Doubles\FakeContainer::new(['foo' => 'subFoo', 'bar' => 'subBar']) | ||
]); | ||
|
||
$this->assertSame('subFoo + subBar', $container->get('foo')); | ||
} | ||
|
||
public function testContainerWithTrackedRecords_getEntryWithUndefinedReferences_ThrowsExceptionWithCallStack() | ||
{ | ||
$records = [ | ||
'foo' => Doubles\MockedRecord::new(function (ContainerInterface $c) { return $c->get('sub.foo') . $c->get('bar'); }), | ||
'bar' => Doubles\MockedRecord::new(function (ContainerInterface $c) { return $c->get('sub.undefined'); }) | ||
]; | ||
|
||
$containers = [ | ||
'sub' => Doubles\FakeContainer::new(['foo' => 'subFoo']) | ||
]; | ||
|
||
$container = new CompositeContainer(new Records\TrackedRecords($records), $containers); | ||
|
||
$this->expectException(NotFoundExceptionInterface::class); | ||
$this->expectExceptionMessage('MockedContainer: missing `undefined` entry [call stack: foo->bar->...]'); | ||
$container->get('foo'); | ||
} | ||
|
||
private function container(array $records = [], array $containers = []) | ||
{ | ||
return new CompositeContainer(new Records($records), $containers); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of Polymorphine/Container package. | ||
* | ||
* (c) Shudd3r <q3.shudder@gmail.com> | ||
* | ||
* This source file is subject to the MIT license that is bundled | ||
* with this source code in the file LICENSE. | ||
*/ | ||
|
||
namespace Polymorphine\Container\Tests; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Polymorphine\Container\ConfigContainer; | ||
use Psr\Container\ContainerInterface; | ||
use Psr\Container\NotFoundExceptionInterface; | ||
|
||
|
||
class ConfigContainerTest extends TestCase | ||
{ | ||
public function testInstantiation() | ||
{ | ||
$this->assertInstanceOf(ContainerInterface::class, $this->container()); | ||
} | ||
|
||
public function testContainer_has_ReturnsTrueForDefinedKeyPaths() | ||
{ | ||
$container = $this->container(); | ||
|
||
$this->assertFalse($container->has('missing')); | ||
$this->assertTrue($container->has('foo1')); | ||
$this->assertFalse($container->has('foo1.undefined')); | ||
$this->assertTrue($container->has('foo1.bar1')); | ||
$this->assertTrue($container->has('foo1.bar1.baz1')); | ||
$this->assertTrue($container->has('foo1.bar2')); | ||
$this->assertFalse($container->has('foo1.bar2.missing')); | ||
$this->assertTrue($container->has('foo2')); | ||
$this->assertTrue($container->has('foo2.bar')); | ||
$this->assertTrue($container->has('foo2.bar.baz')); | ||
$this->assertFalse($container->has('foo2.bar.baz.qux')); | ||
$this->assertTrue($container->has('foo3')); | ||
$this->assertFalse($container->has('foo3.more')); | ||
} | ||
|
||
public function testContainer_getForDefinedKeyPath_ReturnsValueDefinedWithThisPath() | ||
{ | ||
$container = $this->container($config); | ||
|
||
$this->assertSame($config['foo1'], $container->get('foo1')); | ||
$this->assertSame($config['foo1']['bar1'], $container->get('foo1.bar1')); | ||
$this->assertSame($config['foo1']['bar1']['baz1'], $container->get('foo1.bar1.baz1')); | ||
$this->assertSame($config['foo1']['bar2'], $container->get('foo1.bar2')); | ||
$this->assertSame($config['foo2'], $container->get('foo2')); | ||
$this->assertSame($config['foo2']['bar'], $container->get('foo2.bar')); | ||
$this->assertSame($config['foo2']['bar']['baz'], $container->get('foo2.bar.baz')); | ||
$this->assertSame($config['foo3'], $container->get('foo3')); | ||
} | ||
|
||
/** | ||
* @dataProvider undefinedEntries | ||
* | ||
* @param string $id | ||
*/ | ||
public function testContainer_getUndefinedValue_ThrowsException(string $id) | ||
{ | ||
$container = $this->container(); | ||
$this->expectException(NotFoundExceptionInterface::class); | ||
$container->get($id); | ||
} | ||
|
||
public function undefinedEntries() | ||
{ | ||
return [['missing'], ['foo1.undefined'], ['foo1.bar2.missing'], ['foo2.bar.baz.qux'], ['foo3.more']]; | ||
} | ||
|
||
private function container(?array &$config = []) | ||
{ | ||
if (!$config) { | ||
$config = [ | ||
'foo1' => ['bar1' => ['baz1' => 'fooBarBazValue', 'baz2' => null], 'bar2' => 'fooBarValue'], | ||
'foo2' => ['bar' => ['baz' => '']], | ||
'foo3' => null | ||
]; | ||
} | ||
|
||
return new ConfigContainer($config); | ||
} | ||
} |
Oops, something went wrong.