diff --git a/.gitattributes b/.gitattributes
index 8de27b2d9..53c3f3747 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -8,9 +8,10 @@
/docker export-ignore
/fixtures export-ignore
/tests export-ignore
-Makefile export-ignore
codecov.yml export-ignore
+e2e-test.sh export-ignore
ecs.php export-ignore
+Makefile export-ignore
phpunit.xml.dist export-ignore
psalm-baseline.xml export-ignore
psalm.xml.dist export-ignore
diff --git a/e2e-test.sh b/e2e-test.sh
new file mode 100755
index 000000000..b8585ff85
--- /dev/null
+++ b/e2e-test.sh
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+set -e
+# set -x
+
+#######################################################################################################################
+# This script runs semi end-to-end tests for Mockery.
+#
+# It clones the repositories listed in the `projects` array,
+# installs Mockery from the local filesystem,
+# and runs PHPUnit for each PHP version listed in the `php_versions` array.
+#
+# This is useful to test Mockery against different versions of other projects and frameworks.
+#
+#######################################################################################################################
+
+php_versions=(
+ "8.2"
+ "8.3"
+)
+
+projects=(
+ "Brain-WP/BrainMonkey"
+ "filp/whoops"
+ "laravel/framework"
+)
+
+mockery_path="$(pwd)"
+
+resources_path="$mockery_path/../mockery-resources"
+
+mockery_branch=$(git -C "$mockery_path" rev-parse --abbrev-ref HEAD)
+mockery_sha=$(git -C "$mockery_path" rev-parse HEAD | cut -c1-8)
+mockery_version="dev-$mockery_branch#$mockery_sha"
+
+echo "===> Running e2e tests"
+echo "PHP versions: [ ${php_versions[*]} ]"
+echo "Test Projects: [ ${projects[*]} ]"
+echo " "
+echo "Mockery branch: $mockery_branch"
+echo "Mockery SHA: $mockery_sha"
+echo "Mockery version: $mockery_version"
+echo "Mockery path: $mockery_path"
+echo "Resource path: $resources_path"
+echo " "
+
+
+mkdir -p "$resources_path" || { echo "Failed to create directory $resources_path"; exit 1; }
+cd "$resources_path" || { echo "Failed to change directory to $resources_path"; exit 1; }
+
+for project in "${projects[@]}"
+do
+ project_path="$resources_path/$project"
+
+ if [ ! -d "$project_path" ]; then
+ echo "Cloning $project to $project_path"
+
+ git clone "git@github.com:$project.git" "$project_path" --depth=10 || { echo "Failed to clone $project"; exit 1; }
+ else
+ echo "Pulling $project"
+
+ git -C "$project_path" fetch --depth=10 || { echo "Failed to fetch $project"; exit 1; }
+
+ git -C "$project_path" pull || { echo "Failed to pull $project"; exit 1; }
+ fi
+
+ cd "$project_path" || { echo "Failed to change directory to $project_path"; exit 1; }
+
+ echo "Installing Mockery version $mockery_version"
+
+ for php_version in "${php_versions[@]}"
+ do
+ echo "Running PHPUnit for PHP version $php_version"
+
+ docker run -it --rm -v "$mockery_path":/opt/mockery -v "$project_path":/opt/workspace -w /opt/workspace ghcr.io/ghostwriter/php:"$php_version"-pcov sh -c "composer config repositories.local '{\"type\": \"path\", \"url\": \"/opt/mockery\"}' && composer require 'mockery/mockery:$mockery_version' --with-dependencies --ignore-platform-reqs --no-scripts --no-plugins --dev --no-interaction && php vendor/bin/phpunit" || { echo "Failed to run PHPUnit for $project PHP version $php_version"; exit 1; }
+ done
+done
+
+rm -rf "$resources_path" || { echo "Failed to remove directory $resources_path"; exit 1; }
diff --git a/library/Mockery/Exception/BadMethodCallException.php b/library/Mockery/Exception/BadMethodCallException.php
index 6567c22c5..edc0c69d5 100644
--- a/library/Mockery/Exception/BadMethodCallException.php
+++ b/library/Mockery/Exception/BadMethodCallException.php
@@ -21,10 +21,6 @@ public function dismiss()
$this->dismissed = true;
// we sometimes stack them
$previous = $this->getPrevious();
- if (! $previous instanceof Throwable) {
- return;
- }
-
if (! $previous instanceof self) {
return;
}
diff --git a/library/Mockery/Expectation.php b/library/Mockery/Expectation.php
index af4d3848e..ef3ff1b2c 100644
--- a/library/Mockery/Expectation.php
+++ b/library/Mockery/Expectation.php
@@ -928,22 +928,6 @@ protected function _matchArg($expected, &$actual)
return true;
}
- if (is_string($expected) && is_object($actual)) {
- $result = $actual instanceof $expected;
-
- if ($result) {
- return true;
- }
- }
-
- if (is_object($expected)) {
- $matcher = Mockery::getConfiguration()->getDefaultMatcher(get_class($expected));
-
- if ($matcher !== null) {
- $expected = new $matcher($expected);
- }
- }
-
if ($expected instanceof MatcherInterface) {
return $expected->match($actual);
}
@@ -958,7 +942,17 @@ protected function _matchArg($expected, &$actual)
return $expected->matches($actual);
}
- return false;
+ if (is_object($expected)) {
+ $matcher = Mockery::getConfiguration()->getDefaultMatcher(get_class($expected));
+
+ return $matcher === null ? false : $this->_matchArg(new $matcher($expected), $actual);
+ }
+
+ if (is_object($actual) && is_string($expected) && $actual instanceof $expected) {
+ return true;
+ }
+
+ return $expected == $actual;
}
/**
@@ -971,7 +965,7 @@ protected function _matchArg($expected, &$actual)
protected function _matchArgs($args)
{
for ($index = 0, $argCount = count($args); $index < $argCount; ++$index) {
- $param =&$args[$index];
+ $param = &$args[$index];
if (! $this->_matchArg($this->_expectedArgs[$index], $param)) {
return false;
diff --git a/library/Mockery/Mock.php b/library/Mockery/Mock.php
index e52e7724c..71ad448a9 100644
--- a/library/Mockery/Mock.php
+++ b/library/Mockery/Mock.php
@@ -202,7 +202,7 @@ public function mockery_init(Container $container = null, $partialObject = null,
$this->_mockery_instanceMock = $instanceMock;
- $this->parentClass = get_parent_class($this);
+ $this->_mockery_parentClass = get_parent_class($this);
}
/**
@@ -644,15 +644,15 @@ public function __isset($name)
return false;
}
- if (!$this->parentClass) {
+ if (!$this->_mockery_parentClass) {
return false;
}
- if (!method_exists($this->parentClass, '__isset')) {
+ if (!method_exists($this->_mockery_parentClass, '__isset')) {
return false;
}
- return call_user_func($this->parentClass . '::__isset', $name);
+ return call_user_func($this->_mockery_parentClass . '::__isset', $name);
}
public function mockery_getExpectations()
@@ -671,11 +671,11 @@ public function mockery_getExpectations()
*/
public function mockery_callSubjectMethod($name, array $args)
{
- if (!method_exists($this, $name) && $this->parentClass && method_exists($this->parentClass, '__call')) {
- return call_user_func($this->parentClass . '::__call', $name, $args);
+ if (!method_exists($this, $name) && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
+ return call_user_func($this->_mockery_parentClass . '::__call', $name, $args);
}
- return call_user_func_array($this->parentClass . '::' . $name, $args);
+ return call_user_func_array($this->_mockery_parentClass . '::' . $name, $args);
}
/**
@@ -910,7 +910,7 @@ protected function _mockery_handleMethodCall($method, array $args)
// noop - there is no hasPrototype method
}
- return call_user_func_array($this->parentClass . '::' . $method, $args);
+ return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
$handler = $this->_mockery_findExpectedMethodHandler($method);
@@ -930,13 +930,13 @@ protected function _mockery_handleMethodCall($method, array $args)
return $this->_mockery_partial->{$method}(...$args);
}
- if ($this->_mockery_deferMissing && is_callable($this->parentClass . '::' . $method)
- && (!$this->hasMethodOverloadingInParentClass() || ($this->parentClass && method_exists($this->parentClass, $method)))) {
- return call_user_func_array($this->parentClass . '::' . $method, $args);
+ if ($this->_mockery_deferMissing && is_callable($this->_mockery_parentClass . '::' . $method)
+ && (!$this->hasMethodOverloadingInParentClass() || ($this->_mockery_parentClass && method_exists($this->_mockery_parentClass, $method)))) {
+ return call_user_func_array($this->_mockery_parentClass . '::' . $method, $args);
}
- if ($this->_mockery_deferMissing && $this->parentClass && method_exists($this->parentClass, '__call')) {
- return call_user_func($this->parentClass . '::__call', $method, $args);
+ if ($this->_mockery_deferMissing && $this->_mockery_parentClass && method_exists($this->_mockery_parentClass, '__call')) {
+ return call_user_func($this->_mockery_parentClass . '::__call', $method, $args);
}
if ($method === '__toString') {
@@ -946,7 +946,7 @@ protected function _mockery_handleMethodCall($method, array $args)
return sprintf('%s#%s', self::class, spl_object_hash($this));
}
- if ($this->_mockery_ignoreMissing && (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable($this->parentClass . '::' . $method))) {
+ if ($this->_mockery_ignoreMissing && (\Mockery::getConfiguration()->mockingNonExistentMethodsAllowed() || (!is_null($this->_mockery_partial) && method_exists($this->_mockery_partial, $method)) || is_callable($this->_mockery_parentClass . '::' . $method))) {
if ($this->_mockery_defaultReturnValue instanceof Undefined) {
return $this->_mockery_defaultReturnValue->{$method}(...$args);
}
@@ -995,7 +995,7 @@ protected function mockery_getMethods()
private function hasMethodOverloadingInParentClass()
{
// if there's __call any name would be callable
- return is_callable($this->parentClass . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
+ return is_callable($this->_mockery_parentClass . '::aFunctionNameThatNoOneWouldEverUseInRealLife12345');
}
/**
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 3a101fed5..f2feecb15 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -335,6 +335,7 @@
allowMockingNonExistentMethods
disableReflectionCache
enableReflectionCache
+ getDefaultMatcher
getInternalClassMethodParamMap
mockingMethodsUnnecessarilyAllowed
reflectionCacheEnabled
@@ -791,7 +792,6 @@
mockery_allocateOrder
mockery_getGroups
mockery_setGroup
- new $matcher($expected)
validate
diff --git a/tests/Mockery/ExpectationTest.php b/tests/Mockery/ExpectationTest.php
index 514815de3..7dab9dcf6 100644
--- a/tests/Mockery/ExpectationTest.php
+++ b/tests/Mockery/ExpectationTest.php
@@ -2158,6 +2158,20 @@ public function it_uses_a_matchers_to_string_method_in_the_exception_output()
Mockery::close();
}
+
+ public function testNonObjectEqualsExpectation()
+ {
+ $input = ['club_id' => 1, 'user_id' => 1, 'is_admin' => 1];
+
+ $foo = Mockery::mock();
+
+ $foo->shouldReceive('foo')->with($input)->andReturn('foobar');
+
+ // only sort the input to change the order but not the values.
+ ksort($input);
+
+ self::assertSame('foobar', $foo->foo($input));
+ }
}
interface IWater