From f4b43d72af9fd95c3ec6727ccbb65fece0860bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Thu, 21 Jul 2022 10:13:10 +0200 Subject: [PATCH] Consistent checks to ensure container factory returns expected class --- src/Container.php | 10 ++++++++-- tests/ContainerTest.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Container.php b/src/Container.php index 793e287..eb0af03 100644 --- a/src/Container.php +++ b/src/Container.php @@ -127,7 +127,12 @@ private function load(string $name, int $depth = 64) throw new \BadMethodCallException('Factory for ' . $name . ' is recursive'); } - $this->container[$name] = $this->load($this->container[$name], $depth - 1); + $value = $this->load($this->container[$name], $depth - 1); + if (!$value instanceof $name) { + throw new \BadMethodCallException('Factory for ' . $name . ' returned unexpected ' . (is_object($value) ? get_class($value) : gettype($value))); + } + + $this->container[$name] = $value; } elseif ($this->container[$name] instanceof \Closure) { // build list of factory parameters based on parameter types $closure = new \ReflectionFunction($this->container[$name]); @@ -142,7 +147,8 @@ private function load(string $name, int $depth = 64) } $value = $this->load($value, $depth - 1); - } elseif (!$value instanceof $name) { + } + if (!$value instanceof $name) { throw new \BadMethodCallException('Factory for ' . $name . ' returned unexpected ' . (is_object($value) ? get_class($value) : gettype($value))); } diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 3c21d09..e7277eb 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -280,6 +280,36 @@ public function testCallableReturnsCallableThatThrowsWhenFactoryReturnsInvalidIn $callable($request); } + public function testCallableReturnsCallableThatThrowsWhenMapReferencesClassNameThatDoesNotMatchType() + { + $request = new ServerRequest('GET', 'http://example.com/'); + + $container = new Container([ + \stdClass::class => Response::class + ]); + + $callable = $container->callable(\stdClass::class); + + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('Factory for stdClass returned unexpected React\Http\Message\Response'); + $callable($request); + } + + public function testCallableReturnsCallableThatThrowsWhenFactoryReturnsClassNameThatDoesNotMatchType() + { + $request = new ServerRequest('GET', 'http://example.com/'); + + $container = new Container([ + \stdClass::class => function () { return Response::class; } + ]); + + $callable = $container->callable(\stdClass::class); + + $this->expectException(\BadMethodCallException::class); + $this->expectExceptionMessage('Factory for stdClass returned unexpected React\Http\Message\Response'); + $callable($request); + } + public function testCallableReturnsCallableThatThrowsWhenFactoryRequiresInvalidClassName() { $request = new ServerRequest('GET', 'http://example.com/');