/blog/vendor/phpspec/phpspec/src/PhpSpec/Matcher/ThrowMatcher.php
https://gitlab.com/zan_zan/laravel_sample · PHP · 275 lines · 164 code · 32 blank · 79 comment · 20 complexity · 20c398ef19f28952359134eb31fc6b37 MD5 · raw file
- <?php
- /*
- * This file is part of PhpSpec, A php toolset to drive emergent
- * design by specification.
- *
- * (c) Marcello Duarte <marcello.duarte@gmail.com>
- * (c) Konstantin Kudryashov <ever.zet@gmail.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace PhpSpec\Matcher;
- use PhpSpec\Formatter\Presenter\PresenterInterface;
- use PhpSpec\Wrapper\Unwrapper;
- use PhpSpec\Wrapper\DelayedCall;
- use PhpSpec\Factory\ReflectionFactory;
- use PhpSpec\Exception\Example\MatcherException;
- use PhpSpec\Exception\Example\FailureException;
- use PhpSpec\Exception\Example\NotEqualException;
- use PhpSpec\Exception\Fracture\MethodNotFoundException;
- class ThrowMatcher implements MatcherInterface
- {
- /**
- * @var array
- */
- private static $ignoredProperties = array('file', 'line', 'string', 'trace', 'previous');
- /**
- * @var \PhpSpec\Wrapper\Unwrapper
- */
- private $unwrapper;
- /**
- * @var \PhpSpec\Formatter\Presenter\PresenterInterface
- */
- private $presenter;
- /**
- * @var ReflectionFactory
- */
- private $factory;
- /**
- * @param Unwrapper $unwrapper
- * @param PresenterInterface $presenter
- * @param ReflectionFactory $factory
- */
- public function __construct(Unwrapper $unwrapper, PresenterInterface $presenter, ReflectionFactory $factory = null)
- {
- $this->unwrapper = $unwrapper;
- $this->presenter = $presenter;
- $this->factory = $factory ?: new ReflectionFactory();
- }
- /**
- * @param string $name
- * @param mixed $subject
- * @param array $arguments
- *
- * @return bool
- */
- public function supports($name, $subject, array $arguments)
- {
- return 'throw' === $name;
- }
- /**
- * @param string $name
- * @param mixed $subject
- * @param array $arguments
- *
- * @return DelayedCall
- */
- public function positiveMatch($name, $subject, array $arguments)
- {
- return $this->getDelayedCall(array($this, 'verifyPositive'), $subject, $arguments);
- }
- /**
- * @param string $name
- * @param mixed $subject
- * @param array $arguments
- *
- * @return DelayedCall
- */
- public function negativeMatch($name, $subject, array $arguments)
- {
- return $this->getDelayedCall(array($this, 'verifyNegative'), $subject, $arguments);
- }
- /**
- * @param callable $callable
- * @param array $arguments
- * @param null $exception
- *
- * @throws \PhpSpec\Exception\Example\FailureException
- * @throws \PhpSpec\Exception\Example\NotEqualException
- */
- public function verifyPositive($callable, array $arguments, $exception = null)
- {
- try {
- call_user_func_array($callable, $arguments);
- } catch (\Exception $e) {
- if (null === $exception) {
- return;
- }
- if (!$e instanceof $exception) {
- throw new FailureException(sprintf(
- 'Expected exception of class %s, but got %s.',
- $this->presenter->presentValue($exception),
- $this->presenter->presentValue($e)
- ));
- }
- if (is_object($exception)) {
- $exceptionRefl = $this->factory->create($exception);
- foreach ($exceptionRefl->getProperties() as $property) {
- if (in_array($property->getName(), self::$ignoredProperties)) {
- continue;
- }
- $property->setAccessible(true);
- $expected = $property->getValue($exception);
- $actual = $property->getValue($e);
- if (null !== $expected && $actual !== $expected) {
- throw new NotEqualException(sprintf(
- 'Expected exception `%s` to be %s, but it is %s.',
- $property->getName(),
- $this->presenter->presentValue($expected),
- $this->presenter->presentValue($actual)
- ), $expected, $actual);
- }
- }
- }
- return;
- }
- throw new FailureException('Expected to get exception, none got.');
- }
- /**
- * @param callable $callable
- * @param array $arguments
- * @param string|null $exception
- *
- * @throws \PhpSpec\Exception\Example\FailureException
- */
- public function verifyNegative($callable, array $arguments, $exception = null)
- {
- try {
- call_user_func_array($callable, $arguments);
- } catch (\Exception $e) {
- if (null === $exception) {
- throw new FailureException(sprintf(
- 'Expected to not throw any exceptions, but got %s.',
- $this->presenter->presentValue($e)
- ));
- }
- if ($e instanceof $exception) {
- $invalidProperties = array();
- if (is_object($exception)) {
- $exceptionRefl = $this->factory->create($exception);
- foreach ($exceptionRefl->getProperties() as $property) {
- if (in_array($property->getName(), self::$ignoredProperties)) {
- continue;
- }
- $property->setAccessible(true);
- $expected = $property->getValue($exception);
- $actual = $property->getValue($e);
- if (null !== $expected && $actual === $expected) {
- $invalidProperties[] = sprintf(
- ' `%s`=%s',
- $property->getName(),
- $this->presenter->presentValue($expected)
- );
- }
- }
- }
- $withProperties = '';
- if (count($invalidProperties) > 0) {
- $withProperties = sprintf(
- ' with'.PHP_EOL.'%s,'.PHP_EOL,
- implode(",\n", $invalidProperties)
- );
- }
- throw new FailureException(sprintf(
- 'Expected to not throw %s exception%s but got it.',
- $this->presenter->presentValue($exception),
- $withProperties
- ));
- }
- }
- }
- /**
- * @return int
- */
- public function getPriority()
- {
- return 1;
- }
- /**
- * @param callable $check
- * @param mixed $subject
- * @param array $arguments
- *
- * @return DelayedCall
- */
- private function getDelayedCall($check, $subject, array $arguments)
- {
- $exception = $this->getException($arguments);
- $unwrapper = $this->unwrapper;
- return new DelayedCall(
- function ($method, $arguments) use ($check, $subject, $exception, $unwrapper) {
- $arguments = $unwrapper->unwrapAll($arguments);
- $methodName = $arguments[0];
- $arguments = isset($arguments[1]) ? $arguments[1] : array();
- $callable = array($subject, $methodName);
- list($class, $methodName) = array($subject, $methodName);
- if (!method_exists($class, $methodName) && !method_exists($class, '__call')) {
- throw new MethodNotFoundException(
- sprintf('Method %s::%s not found.', get_class($class), $methodName),
- $class,
- $methodName,
- $arguments
- );
- }
- return call_user_func($check, $callable, $arguments, $exception);
- }
- );
- }
- /**
- * @param array $arguments
- *
- * @return null|string
- * @throws \PhpSpec\Exception\Example\MatcherException
- */
- private function getException(array $arguments)
- {
- if (0 == count($arguments)) {
- return null;
- }
- if (is_string($arguments[0])) {
- return $arguments[0];
- }
- if (is_object($arguments[0]) && $arguments[0] instanceof \Exception) {
- return $arguments[0];
- }
- throw new MatcherException(sprintf(
- "Wrong argument provided in throw matcher.\n".
- "Fully qualified classname or exception instance expected,\n".
- "Got %s.",
- $this->presenter->presentValue($arguments[0])
- ));
- }
- }