Skip to content

Commit

Permalink
Reorganized tests
Browse files Browse the repository at this point in the history
- Split tests into files testing individual components
- Added test doubles for component independence
- Redesigned example classes
  • Loading branch information
shudd3r committed Nov 27, 2019
2 parents c4bce6b + 364064c commit d32db11
Show file tree
Hide file tree
Showing 21 changed files with 1,182 additions and 656 deletions.
138 changes: 138 additions & 0 deletions tests/CompositeContainerTest.php
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);
}
}
89 changes: 89 additions & 0 deletions tests/ConfigContainerTest.php
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);
}
}
Loading

0 comments on commit d32db11

Please sign in to comment.