Skip to content

Commit

Permalink
Configurable default matchers
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinMystikJonas committed Feb 24, 2021
1 parent 1dadfa2 commit 8907c7b
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 0 deletions.
41 changes: 41 additions & 0 deletions library/Mockery/Configuration.php
Expand Up @@ -74,6 +74,13 @@ public function __construct()
*/
protected $_objectFormatters = array();

/**
* Default argument matchers
*
* @var array
*/
protected $_defaultMatchers = array();

/**
* Set boolean to allow/prevent mocking of non-existent methods
*
Expand Down Expand Up @@ -239,4 +246,38 @@ public function getObjectFormatter($class, $defaultFormatter)
}
return $defaultFormatter;
}

/**
* @param string $class
* @param string $matcherClass
*/
public function setDefaultMatcher($class, $matcherClass)
{
if (!is_a($matcherClass, \Mockery\Matcher\MatcherAbstract::class, true) &&
!is_a($matcherClass, \Hamcrest\Matcher::class, true) &&
!is_a($matcherClass, \Hamcrest_Matcher::class, true)
) {
throw new \InvalidArgumentException(
"Matcher class must be either Hamcrest matcher or extend \Mockery\Matcher\MatcherAbstract, " .
"'$matcherClass' given."
);
}
$this->_defaultMatchers[$class] = $matcherClass;
}

public function getDefaultMatcher($class)
{
$parentClass = $class;
do {
$classes[] = $parentClass;
$parentClass = get_parent_class($parentClass);
} while ($parentClass);
$classesAndInterfaces = array_merge($classes, class_implements($class));
foreach ($classesAndInterfaces as $type) {
if (isset($this->_defaultMatchers[$type])) {
return $this->_defaultMatchers[$type];
}
}
return null;
}
}
6 changes: 6 additions & 0 deletions library/Mockery/Expectation.php
Expand Up @@ -389,6 +389,12 @@ protected function _matchArg($expected, &$actual)
return true;
}
}
if (is_object($expected)) {
$matcher = \Mockery::getConfiguration()->getDefaultMatcher(get_class($expected));
if ($matcher !== null) {
$expected = new $matcher($expected);
}
}
if ($expected instanceof \Mockery\Matcher\MatcherAbstract) {
return $expected->match($actual);
}
Expand Down
89 changes: 89 additions & 0 deletions tests/Mockery/DefaultMatchersTest.php
@@ -0,0 +1,89 @@
<?php
/**
* Mockery
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://github.com/padraic/mockery/master/LICENSE
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to padraic@php.net so we can send you a copy immediately.
*
* @category Mockery
* @package Mockery
* @subpackage UnitTests
* @copyright Copyright (c) 2010 Pádraic Brady (http://blog.astrumfutura.com)
* @license http://github.com/padraic/mockery/blob/master/LICENSE New BSD License
*/

use Mockery\Adapter\Phpunit\MockeryTestCase;

class CustomValueObjectMatcher extends \Mockery\Matcher\MatcherAbstract
{
public function match(&$actual)
{
return $actual->value === $this->_expected->value;
}

public function __toString()
{
return "<customMatcher>";
}
}

interface CustomValueObjectInterface
{
}

class CustomValueObject implements CustomValueObjectInterface
{
public $value;

public function __construct($value)
{
$this->value = $value;
}
}

class DefaultMatchersTest extends MockeryTestCase
{
public function mockeryTestSetUp()
{
parent::mockeryTestSetUp();
$this->mock = mock('foo');
}


public function mockeryTestTearDown()
{
\Mockery::getConfiguration()->allowMockingNonExistentMethods(true);
parent::mockeryTestTearDown();
}

/** Just a quickie roundup of a few Hamcrest matchers to check nothing obvious out of place **/

public function testDefaultMatcherHamcrest()
{
\Mockery::getConfiguration()->setDefaultMatcher(\DateTime::class, \Hamcrest\Core\IsEqual::class);
$this->mock->shouldReceive('foo')->with(new DateTime("2000-01-01"))->once();
$this->mock->foo(new DateTime("2000-01-01"));
}

public function testDefaultMatcherClass()
{
\Mockery::getConfiguration()->setDefaultMatcher(CustomValueObject::class, CustomValueObjectMatcher::class);
$this->mock->shouldReceive('foo')->with(new CustomValueObject("expected"))->once();
$this->mock->foo(new CustomValueObject("expected"));
}

public function testDefaultMatcherInterface()
{
\Mockery::getConfiguration()->setDefaultMatcher(CustomValueObjectInterface::class, CustomValueObjectMatcher::class);
$this->mock->shouldReceive('foo')->with(new CustomValueObject("expected2"))->once();
$this->mock->foo(new CustomValueObject("expected2"));
}

}

0 comments on commit 8907c7b

Please sign in to comment.