Skip to content

Commit

Permalink
Merge pull request #1032 from robertbasic/revert-exception-debugging
Browse files Browse the repository at this point in the history
Revert exception debugging
  • Loading branch information
robertbasic committed Dec 26, 2019
2 parents c216606 + 580b98c commit f69bbde
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 174 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Change Log

## 1.3.1 (2019-12-26)
* Revert improved exception debugging due to BC breaks (#1032)

## 1.3.0 (2019-11-24)

* Added capture `Mockery::capture` convenience matcher (#1020)
Expand Down
3 changes: 1 addition & 2 deletions composer.json
Expand Up @@ -33,8 +33,7 @@
"require": {
"php": ">=5.6.0",
"lib-pcre": ">=7.0",
"hamcrest/hamcrest-php": "~2.0",
"sebastian/comparator": "^1.2.4|^3.0"
"hamcrest/hamcrest-php": "~2.0"
},
"require-dev": {
"phpunit/phpunit": "~5.7.10|~6.5|~7.0|~8.0"
Expand Down
169 changes: 13 additions & 156 deletions library/Mockery/Exception/NoMatchingExpectationException.php
Expand Up @@ -20,194 +20,51 @@

namespace Mockery\Exception;

use Hamcrest\Util;
use Mockery;
use SebastianBergmann\Comparator\ComparisonFailure;
use SebastianBergmann\Comparator\Factory;

class NoMatchingExpectationException extends Mockery\Exception
{
/**
* @var string
*/
protected $method;
protected $method = null;

/**
* @var array
*/
protected $actual;
protected $actual = array();

/**
* @var Mockery\MockInterface
*/
protected $mockObject;
protected $mockObject = null;

/**
* @param string $methodName
* @param array $actualArguments
* @param array $expectations
*/
public function __construct(
Mockery\MockInterface $mock,
$methodName,
$actualArguments,
$expectations
) {
$this->setMock($mock);
$this->setMethodName($methodName);
$this->setActualArguments($actualArguments);

$diffs = [];
foreach ($expectations as $expectation) {
$expectedArguments = $expectation->getExpectedArgs();

$diff = $this->diff(
$this->normalizeForDiff($expectedArguments),
$this->normalizeForDiff($actualArguments)
);
if (null === $diff) {
// If we reach this, it means that the exception has not been
// raised by a non-strict equality. So the diff is null.
// We do the comparison again but this time comparing references
// of objects.
$diff = $this->diff(
$this->normalizeForStrictDiff($expectedArguments),
$this->normalizeForStrictDiff($actualArguments)
);
}

$diffs[] = sprintf(
"\n%s::%s with arguments%s",
$expectation->getMock()->mockery_getName(),
$expectation->getName(),
null !== $diff ? $diff : "\n### No diff ###"
);
}

$message = 'No matching expectation found for '
. $this->getMockName() . '::'
. \Mockery::formatArgs($methodName, $actualArguments)
. '. Either the method was unexpected or its arguments matched'
. ' no expected argument list for this method.'
. PHP_EOL . PHP_EOL
. 'Here is the list of available expectations and their diff with actual input:'
. PHP_EOL
. implode('', $diffs);

parent::__construct($message, 0, null);
}

/**
* @return $this
*/
private function setMock(Mockery\MockInterface $mock)
public function setMock(Mockery\LegacyMockInterface $mock)
{
$this->mockObject = $mock;
return $this;
}

/**
* @param string $name
*
* @return $this
*/
private function setMethodName($name)
public function setMethodName($name)
{
$this->method = $name;
return $this;
}

/**
* @param array $count
*
* @return $this
*/
private function setActualArguments($count)
public function setActualArguments($count)
{
$this->actual = $count;
return $this;
}

/**
* @return array
*/
public function getActualArguments()
{
return $this->actual;
}

/**
* @return Mockery\MockInterface
*/
private function getMock()
public function getMock()
{
return $this->mockObject;
}

/**
* @return string
*/
private function getMockName()
public function getMethodName()
{
return $this->getMock()->mockery_getName();
}

/**
* @param array $expectedArguments
* @param array $actualArguments
*
* @return string|null
*/
private function diff($expectedArguments, $actualArguments)
{
$comparatorFactory = new Factory();
$comparator = $comparatorFactory->getComparatorFor(
$expectedArguments,
$actualArguments
);
try {
$comparator->assertEquals($expectedArguments, $actualArguments);
} catch (ComparisonFailure $e) {
return $e->getDiff();
}

return null;
return $this->method;
}

/**
* @param array $args
*
* @return array
*/
private function normalizeForDiff($args)
public function getActualArguments()
{
// Wraps items with an IsEqual matcher if it isn't a matcher already
// in order to be sure to compare same nature objects.
return Util::createMatcherArray($args);
return $this->actual;
}

/**
* @param array $args
*
* @return array
*/
private function normalizeForStrictDiff($args)
public function getMockName()
{
$normalized = [];
foreach ($args as $arg) {
if (!is_object($arg)) {
$normalizedArg = Util::createMatcherArray([$arg]);
$normalized[] = reset($normalizedArg);
continue;
}

$objectRef = function_exists('spl_object_id')
? spl_object_id($arg)
: spl_object_hash($arg);

$normalized[] = get_class($arg).'#ref_'.$objectRef;
}

return $normalized;
return $this->getMock()->mockery_getName();
}
}
8 changes: 0 additions & 8 deletions library/Mockery/Expectation.php
Expand Up @@ -911,12 +911,4 @@ public function getExceptionMessage()
{
return $this->_because;
}

/**
* @return array
*/
public function getExpectedArgs()
{
return $this->_expectedArgs;
}
}
17 changes: 12 additions & 5 deletions library/Mockery/ExpectationDirector.php
Expand Up @@ -89,12 +89,19 @@ public function call(array $args)
{
$expectation = $this->findExpectation($args);
if (is_null($expectation)) {
throw new \Mockery\Exception\NoMatchingExpectationException(
$this->_mock,
$this->_name,
$args,
$this->getExpectations()
$exception = new \Mockery\Exception\NoMatchingExpectationException(
'No matching handler found for '
. $this->_mock->mockery_getName() . '::'
. \Mockery::formatArgs($this->_name, $args)
. '. Either the method was unexpected or its arguments matched'
. ' no expected argument list for this method'
. PHP_EOL . PHP_EOL
. \Mockery::formatObjects($args)
);
$exception->setMock($this->_mock)
->setMethodName($this->_name)
->setActualArguments($args);
throw $exception;
}
return $expectation->verifyCall($args);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Mockery/ContainerTest.php
Expand Up @@ -1239,7 +1239,7 @@ public function testHandlesMethodWithArgumentExpectationWhenCalledWithResource()
$mock->shouldReceive('foo')->with(array('yourself' => 21));

$this->expectException(\Mockery\Exception\NoMatchingExpectationException::class);
$this->expectExceptionMessage("0 => Hamcrest\Core\IsEqual Object (...)");
$this->expectExceptionMessage('MyTestClass::foo(resource(...))');
$mock->foo(fopen('php://memory', 'r'));
}

Expand All @@ -1252,7 +1252,7 @@ public function testHandlesMethodWithArgumentExpectationWhenCalledWithCircularAr
$mock->shouldReceive('foo')->with(array('yourself' => 21));

$this->expectException(\Mockery\Exception\NoMatchingExpectationException::class);
$this->expectExceptionMessage("'myself' => Hamcrest\Core\IsEqual Object (...)");
$this->expectExceptionMessage("MyTestClass::foo(['myself' => [...]])");
$mock->foo($testArray);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Mockery/ExpectationTest.php
Expand Up @@ -1436,7 +1436,7 @@ public function testClassConstraintThrowsExceptionWhenConstraintUnmatched()
{
$this->mock->shouldReceive('foo')->with(Mockery::type('stdClass'));
$this->expectException(\Mockery\Exception::class);
$this->mock->foo(new \DateTime());
$this->mock->foo(new Exception);
Mockery::close();
}

Expand Down

0 comments on commit f69bbde

Please sign in to comment.