more testing and catching things.

pull/559/head
Austin Collier 10 months ago
parent 3f887e305f
commit f752073f7d

@ -339,44 +339,24 @@ class Dispatcher
}
}
// If there's no container handler set, you can use [ 'className', 'methodName' ]
// to call a method dynamically. Nothing is injected into the class though.
if (is_string($class) && class_exists($class)) {
$constructor = (new ReflectionClass($class))->getConstructor();
$constructorParamsNumber = 0;
if ($constructor !== null) {
$constructorParamsNumber = count($constructor->getParameters());
}
if ($constructorParamsNumber > 0) {
$exceptionMessage = "Method '$class::$method' cannot be called statically. ";
$exceptionMessage .= sprintf(
"$class::__construct require $constructorParamsNumber parameter%s",
$constructorParamsNumber > 1 ? 's' : ''
);
throw new InvalidArgumentException($exceptionMessage, E_ERROR);
}
$class = new $class();
}
// Final check to make sure it's actually a class and a method, or throw an error
if (is_object($class) === false) {
// Cause PHPUnit has 1 level of output buffering by default
if(ob_get_level() > (getenv('PHPUNIT_TEST') ? 1 : 0)) {
ob_end_clean();
}
if (is_object($class) === false && class_exists($class) === false) {
$this->fixOutputBuffering();
throw new Exception("Class '$class' not found. Is it being correctly autoloaded with Flight::path()?");
}
// If this tried to resolve a class in a container and failed somehow, throw the exception
if (isset($resolvedClass) === false && self::$container_exception !== null) {
$this->fixOutputBuffering();
throw self::$container_exception;
}
// If we made it this far, we can forget the container exception and move on...
self::$container_exception = null;
// Class is there, but no method
if (method_exists($class, $method) === false) {
// Cause PHPUnit has 1 level of output buffering by default
if(ob_get_level() > (getenv('PHPUNIT_TEST') ? 1 : 0)) {
ob_end_clean();
}
$this->fixOutputBuffering();
throw new Exception("Class found, but method '".get_class($class)."::$method' not found.");
}
@ -445,6 +425,19 @@ class Dispatcher
return $class_object;
}
/**
* Because this could throw an exception in the middle of an output buffer,
*
* @return void
*/
protected function fixOutputBuffering(): void
{
// Cause PHPUnit has 1 level of output buffering by default
if(ob_get_level() > (getenv('PHPUNIT_TEST') ? 1 : 0)) {
ob_end_clean();
}
}
/**
* Resets the object to the initial state.
*

@ -21,6 +21,7 @@ class DispatcherTest extends TestCase
protected function setUp(): void
{
$this->dispatcher = new Dispatcher();
Dispatcher::$container_exception = null;
}
public function testClosureMapping(): void
@ -137,20 +138,6 @@ class DispatcherTest extends TestCase
$this->dispatcher->execute('nonexistentGlobalFunction');
}
public function testInvalidCallbackBecauseConstructorParameters(): void
{
$class = TesterClass::class;
$method = 'instanceMethod';
$exceptionMessage = "Method '$class::$method' cannot be called statically. ";
$exceptionMessage .= "$class::__construct require 6 parameters";
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage($exceptionMessage);
static $params = [];
$this->dispatcher->invokeMethod([$class, $method], $params);
}
// It will be useful for executing instance Controller methods statically
public function testCanExecuteAnNonStaticMethodStatically(): void
{
@ -252,4 +239,12 @@ class DispatcherTest extends TestCase
$this->assertSame('helloparam1param2param3param4param5param6', $result);
}
public function testInvokeMethod(): void
{
$class = new TesterClass('param1', 'param2', 'param3', 'param4', 'param5', 'param6');
$result = $this->dispatcher->invokeMethod([ $class, 'instanceMethod' ]);
$this->assertSame('param1', $class->param2);
}
}

@ -5,12 +5,13 @@ declare(strict_types=1);
namespace tests;
use Exception;
use Flight;
use flight\core\Dispatcher;
use flight\database\PdoWrapper;
use flight\Engine;
use flight\net\Request;
use flight\net\Response;
use flight\util\Collection;
use PDOException;
use PHPUnit\Framework\TestCase;
use tests\classes\Container;
@ -20,6 +21,7 @@ class EngineTest extends TestCase
public function setUp(): void
{
$_SERVER = [];
Dispatcher::$container_exception = null;
}
public function tearDown(): void
@ -682,6 +684,12 @@ class EngineTest extends TestCase
public function testContainerDice() {
$engine = new Engine();
$dice = new \Dice\Dice();
$dice = $dice->addRules([
PdoWrapper::class => [
'shared' => true,
'constructParams' => [ 'sqlite::memory:' ]
]
]);
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
return $dice->create($class, $params);
});
@ -693,6 +701,42 @@ class EngineTest extends TestCase
$this->expectOutputString('yay! I injected a collection, and it has 1 items');
}
public function testContainerDicePdoWrapperTest() {
$engine = new Engine();
$dice = new \Dice\Dice();
$dice = $dice->addRules([
PdoWrapper::class => [
'shared' => true,
'constructParams' => [ 'sqlite::memory:' ]
]
]);
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
return $dice->create($class, $params);
});
$engine->route('/container', Container::class.'->testThePdoWrapper');
$engine->request()->url = '/container';
$engine->start();
$this->expectOutputString('Yay! I injected a PdoWrapper, and it returned the number 5 from the database!');
}
public function testContainerDicePdoWrapperTestBadParams() {
$engine = new Engine();
$dice = new \Dice\Dice();
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
return $dice->create($class, $params);
});
$engine->route('/container', Container::class.'->testThePdoWrapper');
$engine->request()->url = '/container';
$this->expectException(PDOException::class);
$this->expectExceptionMessage("invalid data source name");
$engine->start();
}
public function testContainerDiceBadClass() {
$engine = new Engine();
$dice = new \Dice\Dice();
@ -714,6 +758,12 @@ class EngineTest extends TestCase
public function testContainerDiceBadMethod() {
$engine = new Engine();
$dice = new \Dice\Dice();
$dice = $dice->addRules([
PdoWrapper::class => [
'shared' => true,
'constructParams' => [ 'sqlite::memory:' ]
]
]);
$engine->registerContainerHandler(function ($class, $params) use ($dice) {
return $dice->create($class, $params);
});
@ -732,8 +782,9 @@ class EngineTest extends TestCase
public function testContainerPsr11() {
$engine = new Engine();
$container = new \League\Container\Container();
$container->add(Container::class)->addArgument(Collection::class);
$container->add(Container::class)->addArgument(Collection::class)->addArgument(PdoWrapper::class);
$container->add(Collection::class);
$container->add(PdoWrapper::class)->addArgument('sqlite::memory:');
$engine->registerContainerHandler($container);
$engine->route('/container', Container::class.'->testTheContainer');
@ -762,8 +813,9 @@ class EngineTest extends TestCase
public function testContainerPsr11MethodNotFound() {
$engine = new Engine();
$container = new \League\Container\Container();
$container->add(Container::class)->addArgument(Collection::class);
$container->add(Container::class)->addArgument(Collection::class)->addArgument(PdoWrapper::class);
$container->add(Collection::class);
$container->add(PdoWrapper::class)->addArgument('sqlite::memory:');
$engine->registerContainerHandler($container);
$engine->route('/container', Container::class.'->badMethod');

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace tests;
use Exception;
use flight\core\Dispatcher;
use flight\Engine;
use tests\classes\Hello;
use PHPUnit\Framework\TestCase;
@ -15,6 +16,7 @@ class MapTest extends TestCase
protected function setUp(): void
{
Dispatcher::$container_exception = null;
$this->app = new Engine();
}

@ -4,15 +4,18 @@ declare(strict_types=1);
namespace tests\classes;
use flight\database\PdoWrapper;
use flight\util\Collection;
class Container
{
protected Collection $collection;
protected PdoWrapper $pdoWrapper;
public function __construct(Collection $collection)
public function __construct(Collection $collection, PdoWrapper $pdoWrapper)
{
$this->collection = $collection;
$this->pdoWrapper = $pdoWrapper;
}
public function testTheContainer()
@ -20,4 +23,10 @@ class Container
$this->collection->whatever = 'yay!';
echo 'yay! I injected a collection, and it has ' . $this->collection->count() . ' items';
}
public function testThePdoWrapper()
{
$value = (int) $this->pdoWrapper->fetchField('SELECT 5');
echo 'Yay! I injected a PdoWrapper, and it returned the number ' . $value . ' from the database!';
}
}

Loading…
Cancel
Save