Skip to content

Commit 87e3bfe

Browse files
author
Stephan Wentz
committed
fix: Fix http mock request builder assertions
1 parent ad6943a commit 87e3bfe

File tree

6 files changed

+151
-56
lines changed

6 files changed

+151
-56
lines changed

phpstan.neon.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ parameters:
1010
- '#Constructor in .* has parameter .* with default value#'
1111
- '#SchemaBuilder::foo\(\)#'
1212
ergebnis:
13+
noNamedArgument:
14+
enabled: false
1315
noAssignByReference:
1416
enabled: false
1517
noParameterPassedByReference:

src/HttpClientMock/HttpClientMockTrait.php

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use ArrayObject;
88
use Brainbits\FunctionalTestHelpers\HttpClientMock\Exception\HttpClientMockException;
99
use Monolog\Logger;
10+
use PHPUnit\Framework\Attributes\After;
11+
use PHPUnit\Framework\Attributes\Before;
1012
use PHPUnit\Framework\TestCase;
1113
use Symfony\Component\Console\Event\ConsoleErrorEvent;
1214
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
@@ -22,15 +24,67 @@
2224
use function Safe\parse_url;
2325
use function sprintf;
2426
use function str_contains;
25-
use function trigger_deprecation;
27+
use function trigger_error;
2628
use function ucfirst;
2729
use function urldecode;
2830
use function vsprintf;
2931

32+
use const E_USER_DEPRECATED;
33+
3034
/** @mixin TestCase */
3135
trait HttpClientMockTrait
3236
{
33-
protected function registerNoMatchingMockRequestAsserts(
37+
/** @var list<MockRequestBuilder> */
38+
protected array $createdMockRequestBuilders = [];
39+
/** @var list<string> */
40+
protected array $mockRequestLoggerNames = ['monolog.logger'];
41+
42+
#[Before]
43+
final protected function setUpMockRequestBuilder(): void
44+
{
45+
$container = static::getContainer();
46+
$eventDispatcher = $container->get('event_dispatcher');
47+
assert($eventDispatcher instanceof EventDispatcherInterface);
48+
49+
$loggerNames = $this->mockRequestLoggerNames;
50+
51+
$this->registerNoMatchingMockRequestListeners(
52+
$eventDispatcher,
53+
...array_map(
54+
static function ($loggerName) {
55+
$logger = static::getContainer()->get($loggerName);
56+
assert($logger instanceof Logger);
57+
58+
return $logger;
59+
},
60+
$loggerNames,
61+
),
62+
);
63+
}
64+
65+
#[After]
66+
protected function assertNoFailedMockRequests(): void
67+
{
68+
$mockRequestBuilders = $this->createdMockRequestBuilders;
69+
$this->createdMockRequestBuilders = [];
70+
71+
foreach ($mockRequestBuilders as $mockRequestBuilder) {
72+
foreach ($mockRequestBuilder->getFailedAssertions() as $failedAssertion) {
73+
throw $failedAssertion;
74+
}
75+
}
76+
}
77+
78+
protected function registerNoMatchingMockRequestAsserts(): void
79+
{
80+
// legacy start - remove in 8.0.0
81+
82+
trigger_error('no matching mock request listeners are now automatically registered', E_USER_DEPRECATED);
83+
84+
// legacy end - remove in 8.0.0
85+
}
86+
87+
protected function registerNoMatchingMockRequestListeners(
3488
EventDispatcherInterface $eventDispatcher,
3589
Logger ...$loggers,
3690
): void {
@@ -130,18 +184,13 @@ protected function mockRequest(string|null $method = null, string|callable|null
130184
$stack = self::getContainer()->get(MockRequestBuilderCollection::class);
131185
assert($stack instanceof MockRequestBuilderCollection);
132186

133-
$builder = (new MockRequestBuilder())
187+
$this->createdMockRequestBuilders[] = $builder = (new MockRequestBuilder())
134188
->method($method);
135189

136190
// legacy start - remove in 8.0.0
137191

138192
if (is_string($uri) && str_contains($uri, '?')) {
139-
trigger_deprecation(
140-
'functional-test-helpers',
141-
'7.0.0',
142-
'Query parameters in uri is deprecated. Use %s instead',
143-
'queryParam()',
144-
);
193+
trigger_error('Query parameters in uri is deprecated. Use queryParam() instead', E_USER_DEPRECATED);
145194
$uriParts = parse_url($uri);
146195
$uri = ($uriParts['scheme'] ?? false ? $uriParts['scheme'] . '://' : '') .
147196
($uriParts['host'] ?? false ? $uriParts['host'] : '') .

src/HttpClientMock/MockRequestBuilder.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,23 @@ public function assertThat(callable $assert): self
165165
return $this;
166166
}
167167

168+
/** @var list<Throwable> */
169+
private array $failedAssertions = [];
170+
171+
/** @return list<Throwable> */
172+
public function getFailedAssertions(): array
173+
{
174+
return $this->failedAssertions;
175+
}
176+
168177
public function assert(RealRequest $realRequest): void
169178
{
170179
foreach ($this->assertions as $assertion) {
171-
$assertion($realRequest, $this);
180+
try {
181+
$assertion($realRequest, $this);
182+
} catch (Throwable $e) {
183+
$this->failedAssertions[] = $e;
184+
}
172185
}
173186
}
174187

tests/HttpClientMock/HttpClientMockTraitTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,34 @@
1111
use Brainbits\FunctionalTestHelpers\HttpClientMock\Matcher\UriParams;
1212
use Brainbits\FunctionalTestHelpers\HttpClientMock\MockRequestBuilderCollection;
1313
use Brainbits\FunctionalTestHelpers\HttpClientMock\MockRequestMatcher;
14+
use Monolog\Logger;
15+
use PHPUnit\Framework\Attributes\Before;
1416
use PHPUnit\Framework\TestCase;
1517
use Symfony\Component\DependencyInjection\Container;
18+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
1619

1720
final class HttpClientMockTraitTest extends TestCase
1821
{
1922
use HttpClientMockTrait;
2023

2124
private static MockRequestBuilderCollection|null $collection = null;
25+
private static EventDispatcherInterface|null $dispatcher = null;
26+
private static Logger|null $logger = null;
2227

23-
public function setUp(): void
28+
#[Before(100)]
29+
public function foo(): void
2430
{
2531
self::$collection = new MockRequestBuilderCollection();
32+
self::$dispatcher = $this->createMock(EventDispatcherInterface::class);
33+
self::$logger = $this->createMock(Logger::class);
2634
}
2735

2836
public static function getContainer(): Container
2937
{
3038
$container = new Container();
3139
$container->set(MockRequestBuilderCollection::class, self::$collection);
40+
$container->set('event_dispatcher', self::$dispatcher);
41+
$container->set('monolog.logger', self::$logger);
3242

3343
return $container;
3444
}

tests/HttpClientMock/MockRequestBuilderCollectionTest.php

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPUnit\Framework\AssertionFailedError;
1313
use PHPUnit\Framework\Attributes\CoversClass;
1414
use PHPUnit\Framework\Attributes\DataProvider;
15+
use PHPUnit\Framework\ExpectationFailedException;
1516
use PHPUnit\Framework\TestCase;
1617

1718
#[CoversClass(MockRequestBuilder::class)]
@@ -173,68 +174,74 @@ public function testAssertContent(): void
173174
{
174175
$collection = new MockRequestBuilderCollection();
175176
$collection->addMockRequestBuilder(
176-
(new MockRequestBuilder())
177+
$builder = (new MockRequestBuilder())
177178
->assertContent(function (string $content): void {
178179
$this->assertSame('this is content', $content);
179180
})
180181
->willRespond(new MockResponseBuilder()),
181182
);
182183

183184
$collection('GET', '/query', ['body' => 'this is content']);
185+
186+
$this->assertSame([], $builder->getFailedAssertions());
184187
}
185188

186189
public function testAssertContentFails(): void
187190
{
188191
$collection = new MockRequestBuilderCollection();
189192
$collection->addMockRequestBuilder(
190-
(new MockRequestBuilder())
193+
$builder = (new MockRequestBuilder())
191194
->assertContent(function (string $content): void {
192195
$this->assertSame('this is content', $content);
193196
})
194197
->willRespond(new MockResponseBuilder()),
195198
);
196199

197-
try {
198-
$collection('GET', '/query', ['body' => 'does-not-match']);
199-
} catch (AssertionFailedError) {
200-
return;
201-
}
200+
$collection('GET', '/query', ['body' => 'does-not-match']);
202201

203-
$this->fail('Expected assertion was not thrown');
202+
$failedAssertions = $builder->getFailedAssertions();
203+
$this->assertCount(1, $failedAssertions);
204+
$this->assertInstanceOf(
205+
ExpectationFailedException::class,
206+
$failedAssertions[0],
207+
);
204208
}
205209

206210
public function testAssertThat(): void
207211
{
208212
$collection = new MockRequestBuilderCollection();
209213
$collection->addMockRequestBuilder(
210-
(new MockRequestBuilder())
214+
$builder = (new MockRequestBuilder())
211215
->assertThat(function (RealRequest $realRequest): void {
212216
$this->assertSame('this is content', $realRequest->getContent());
213217
})
214218
->willRespond(new MockResponseBuilder()),
215219
);
216220

217221
$collection('GET', '/query', ['body' => 'this is content']);
222+
223+
$this->assertSame([], $builder->getFailedAssertions());
218224
}
219225

220226
public function testAssertThatFails(): void
221227
{
222228
$collection = new MockRequestBuilderCollection();
223229
$collection->addMockRequestBuilder(
224-
(new MockRequestBuilder())
230+
$builder = (new MockRequestBuilder())
225231
->assertThat(function (RealRequest $realRequest): void {
226232
$this->assertSame('this is content', $realRequest->getContent());
227233
})
228234
->willRespond(new MockResponseBuilder()),
229235
);
230236

231-
try {
232-
$collection('GET', '/query', ['body' => 'does-not-match']);
233-
} catch (AssertionFailedError) {
234-
return;
235-
}
237+
$collection('GET', '/query', ['body' => 'does-not-match']);
236238

237-
$this->fail('Expected assertion was not thrown');
239+
$failedAssertions = $builder->getFailedAssertions();
240+
$this->assertCount(1, $failedAssertions);
241+
$this->assertInstanceOf(
242+
ExpectationFailedException::class,
243+
$failedAssertions[0],
244+
);
238245
}
239246

240247
/** @return mixed[] */

0 commit comments

Comments
 (0)