From 4769815bde958a525b71c8681f535e5fb38217ac Mon Sep 17 00:00:00 2001 From: Danny Smart Date: Tue, 2 May 2023 18:40:45 +0100 Subject: [PATCH] Prevent nested arrays from causing array to string conversion when casting Subset as a string --- CHANGELOG.md | 3 ++- library/Mockery/Matcher/Subset.php | 21 +++++++++++++++------ tests/Mockery/Matcher/SubsetTest.php | 24 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90cb47736..914117b22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Change Log -## 1.5.2 (2022-xx-xx) +## 1.5.2 (2023-xx-xx) +* Prevent array to string conversion when serialising a Subset matcher #1252 * Updated changelog for version 1.5.1 to include changes from #1180 ## 1.3.6 (2022-09-07) diff --git a/library/Mockery/Matcher/Subset.php b/library/Mockery/Matcher/Subset.php index 5e706c81f..d4ec14f13 100644 --- a/library/Mockery/Matcher/Subset.php +++ b/library/Mockery/Matcher/Subset.php @@ -81,12 +81,21 @@ public function match(&$actual) */ public function __toString() { - $return = 'expected as $k=>$v) { - $elements[] = $k . '=' . (string) $v; + return 'formatArray($this->expected) . ">"; + } + + /** + * Recursively format an array into the string representation for this matcher + * + * @param array $array + * @return string + */ + protected function formatArray(array $array) + { + $elements = []; + foreach ($array as $k => $v) { + $elements[] = $k . '=' . (is_array($v) ? $this->formatArray($v) : (string) $v); } - $return .= implode(', ', $elements) . ']>'; - return $return; + return "[" . implode(", ", $elements) . "]"; } } diff --git a/tests/Mockery/Matcher/SubsetTest.php b/tests/Mockery/Matcher/SubsetTest.php index e45e17cf3..a1ba48f30 100644 --- a/tests/Mockery/Matcher/SubsetTest.php +++ b/tests/Mockery/Matcher/SubsetTest.php @@ -94,4 +94,28 @@ public function it_returns_false_if_actual_is_not_an_array() $this->assertFalse($matcher->match($actual)); } + + /** @test */ + public function it_correctly_formats_nested_arrays_into_a_string() + { + $expected = [ + "foo" => 123, + "bar" => [ + "baz" => 456 + ] + ]; + + $matcher = new Subset($expected); + $actual = $matcher->__toString(); + + $tests = [ + "/foo=123/", + "/bar=\\[[^[\\]]+\\]/", // e.g. bar=[] + "/baz=456/" + ]; + + foreach ($tests as $pattern) { + $this->assertMatchesRegularExpression($pattern, $actual); + } + } }