Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 54c59f7

Browse filesBrowse files
committed
[PhpUnitBridge] Enable configuring mock ns with attributes
1 parent bbe1b6e commit 54c59f7
Copy full SHA for 54c59f7

18 files changed

+538
-11
lines changed

‎.github/workflows/phpunit-bridge.yml

Copy file name to clipboardExpand all lines: .github/workflows/phpunit-bridge.yml
+1-1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ jobs:
3535
php-version: "7.2"
3636

3737
- name: Lint
38-
run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {}
38+
run: find ./src/Symfony/Bridge/PhpUnit -name '*.php' | grep -v -e /Tests/ -e /Attribute/ -e /Extension/ -e /Metadata/ -e ForV7 -e ForV8 -e ForV9 -e ConstraintLogicTrait | parallel -j 4 php -l {}

‎composer.json

Copy file name to clipboardExpand all lines: composer.json
+1
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@
185185
"psr-4": {
186186
"Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
187187
"Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/",
188+
"Symfony\\Bridge\\PhpUnit\\": "src/Symfony/Bridge/PhpUnit/",
188189
"Symfony\\Bridge\\PsrHttpMessage\\": "src/Symfony/Bridge/PsrHttpMessage/",
189190
"Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/",
190191
"Symfony\\Bundle\\": "src/Symfony/Bundle/",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PhpUnit\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
15+
final class DnsSensitive
16+
{
17+
public function __construct(
18+
public readonly string $class,
19+
) {
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PhpUnit\Attribute;
13+
14+
#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
15+
final class TimeSensitive
16+
{
17+
public function __construct(
18+
public readonly string $class,
19+
) {
20+
}
21+
}

‎src/Symfony/Bridge/PhpUnit/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/CHANGELOG.md
+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.3
5+
---
6+
7+
* Enable configuring clock and DNS mock namespaces with attributes
8+
49
7.2
510
---
611

‎src/Symfony/Bridge/PhpUnit/Extension/DisableClockMockSubscriber.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Extension/DisableClockMockSubscriber.php
+12
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
use PHPUnit\Event\Test\Finished;
1616
use PHPUnit\Event\Test\FinishedSubscriber;
1717
use PHPUnit\Metadata\Group;
18+
use Symfony\Bridge\PhpUnit\Attribute\TimeSensitive;
1819
use Symfony\Bridge\PhpUnit\ClockMock;
20+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
1921

2022
/**
2123
* @internal
2224
*/
2325
class DisableClockMockSubscriber implements FinishedSubscriber
2426
{
27+
public function __construct(
28+
private AttributeReader $reader,
29+
) {
30+
}
31+
2532
public function notify(Finished $event): void
2633
{
2734
$test = $event->test();
@@ -33,7 +40,12 @@ public function notify(Finished $event): void
3340
foreach ($test->metadata() as $metadata) {
3441
if ($metadata instanceof Group && 'time-sensitive' === $metadata->groupName()) {
3542
ClockMock::withClockMock(false);
43+
break;
3644
}
3745
}
46+
47+
if ($this->reader->forClassAndMethod($test->className(), $test->methodName(), TimeSensitive::class)) {
48+
ClockMock::withClockMock(false);
49+
}
3850
}
3951
}

‎src/Symfony/Bridge/PhpUnit/Extension/DisableDnsMockSubscriber.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Extension/DisableDnsMockSubscriber.php
+12
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
use PHPUnit\Event\Test\Finished;
1616
use PHPUnit\Event\Test\FinishedSubscriber;
1717
use PHPUnit\Metadata\Group;
18+
use Symfony\Bridge\PhpUnit\Attribute\DnsSensitive;
1819
use Symfony\Bridge\PhpUnit\DnsMock;
20+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
1921

2022
/**
2123
* @internal
2224
*/
2325
class DisableDnsMockSubscriber implements FinishedSubscriber
2426
{
27+
public function __construct(
28+
private AttributeReader $reader,
29+
) {
30+
}
31+
2532
public function notify(Finished $event): void
2633
{
2734
$test = $event->test();
@@ -33,7 +40,12 @@ public function notify(Finished $event): void
3340
foreach ($test->metadata() as $metadata) {
3441
if ($metadata instanceof Group && 'dns-sensitive' === $metadata->groupName()) {
3542
DnsMock::withMockedHosts([]);
43+
break;
3644
}
3745
}
46+
47+
if ($this->reader->forClassAndMethod($test->className(), $test->methodName(), DnsSensitive::class)) {
48+
DnsMock::withMockedHosts([]);
49+
}
3850
}
3951
}

‎src/Symfony/Bridge/PhpUnit/Extension/EnableClockMockSubscriber.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Extension/EnableClockMockSubscriber.php
+12
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
use PHPUnit\Event\Test\PreparationStarted;
1616
use PHPUnit\Event\Test\PreparationStartedSubscriber;
1717
use PHPUnit\Metadata\Group;
18+
use Symfony\Bridge\PhpUnit\Attribute\TimeSensitive;
1819
use Symfony\Bridge\PhpUnit\ClockMock;
20+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
1921

2022
/**
2123
* @internal
2224
*/
2325
class EnableClockMockSubscriber implements PreparationStartedSubscriber
2426
{
27+
public function __construct(
28+
private AttributeReader $reader,
29+
) {
30+
}
31+
2532
public function notify(PreparationStarted $event): void
2633
{
2734
$test = $event->test();
@@ -33,7 +40,12 @@ public function notify(PreparationStarted $event): void
3340
foreach ($test->metadata() as $metadata) {
3441
if ($metadata instanceof Group && 'time-sensitive' === $metadata->groupName()) {
3542
ClockMock::withClockMock(true);
43+
break;
3644
}
3745
}
46+
47+
if ($this->reader->forClassAndMethod($test->className(), $test->methodName(), TimeSensitive::class)) {
48+
ClockMock::withClockMock(true);
49+
}
3850
}
3951
}

‎src/Symfony/Bridge/PhpUnit/Extension/RegisterClockMockSubscriber.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Extension/RegisterClockMockSubscriber.php
+11
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
use PHPUnit\Event\TestSuite\Loaded;
1616
use PHPUnit\Event\TestSuite\LoadedSubscriber;
1717
use PHPUnit\Metadata\Group;
18+
use Symfony\Bridge\PhpUnit\Attribute\TimeSensitive;
1819
use Symfony\Bridge\PhpUnit\ClockMock;
20+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
1921

2022
/**
2123
* @internal
2224
*/
2325
class RegisterClockMockSubscriber implements LoadedSubscriber
2426
{
27+
public function __construct(
28+
private AttributeReader $reader,
29+
) {
30+
}
31+
2532
public function notify(Loaded $event): void
2633
{
2734
foreach ($event->testSuite()->tests() as $test) {
@@ -34,6 +41,10 @@ public function notify(Loaded $event): void
3441
ClockMock::register($test->className());
3542
}
3643
}
44+
45+
foreach ($this->reader->forClassAndMethod($test->className(), $test->methodName(), TimeSensitive::class) as $attribute) {
46+
ClockMock::register($attribute->class);
47+
}
3748
}
3849
}
3950
}

‎src/Symfony/Bridge/PhpUnit/Extension/RegisterDnsMockSubscriber.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Extension/RegisterDnsMockSubscriber.php
+11
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,20 @@
1515
use PHPUnit\Event\TestSuite\Loaded;
1616
use PHPUnit\Event\TestSuite\LoadedSubscriber;
1717
use PHPUnit\Metadata\Group;
18+
use Symfony\Bridge\PhpUnit\Attribute\DnsSensitive;
1819
use Symfony\Bridge\PhpUnit\DnsMock;
20+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
1921

2022
/**
2123
* @internal
2224
*/
2325
class RegisterDnsMockSubscriber implements LoadedSubscriber
2426
{
27+
public function __construct(
28+
private AttributeReader $reader,
29+
) {
30+
}
31+
2532
public function notify(Loaded $event): void
2633
{
2734
foreach ($event->testSuite()->tests() as $test) {
@@ -34,6 +41,10 @@ public function notify(Loaded $event): void
3441
DnsMock::register($test->className());
3542
}
3643
}
44+
45+
foreach ($this->reader->forClassAndMethod($test->className(), $test->methodName(), DnsSensitive::class) as $attribute) {
46+
DnsMock::register($attribute->class);
47+
}
3748
}
3849
}
3950
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bridge\PhpUnit\Metadata;
13+
14+
/**
15+
* @template T of object
16+
*/
17+
final class AttributeReader
18+
{
19+
/**
20+
* @var array<string, array<class-string<T>, list<T>>>
21+
*/
22+
private array $cache = [];
23+
24+
/**
25+
* @param class-string $className
26+
* @param class-string<T> $name
27+
*
28+
* @return list<T>
29+
*/
30+
public function forClass(string $className, string $name): array
31+
{
32+
$attributes = $this->cache[$className] ??= $this->readAttributes(new \ReflectionClass($className));
33+
34+
return $attributes[$name] ?? [];
35+
}
36+
37+
/**
38+
* @param class-string $className
39+
* @param class-string<T> $name
40+
*
41+
* @return list<T>
42+
*/
43+
public function forMethod(string $className, string $methodName, string $name): array
44+
{
45+
$attributes = $this->cache[$className.'::'.$methodName] ??= $this->readAttributes(new \ReflectionMethod($className, $methodName));
46+
47+
return $attributes[$name] ?? [];
48+
}
49+
50+
/**
51+
* @param class-string $className
52+
* @param class-string<T> $name
53+
*
54+
* @return list<T>
55+
*/
56+
public function forClassAndMethod(string $className, string $methodName, string $name): array
57+
{
58+
return [
59+
...$this->forClass($className, $name),
60+
...$this->forMethod($className, $methodName, $name),
61+
];
62+
}
63+
64+
private function readAttributes(\ReflectionClass|\ReflectionMethod $reflection): array
65+
{
66+
$attributeInstances = [];
67+
68+
foreach ($reflection->getAttributes() as $attribute) {
69+
if (!str_starts_with($name = $attribute->getName(), 'Symfony\\Bridge\\PhpUnit\\Attribute\\')) {
70+
continue;
71+
}
72+
73+
$attributeInstances[$name][] = $attribute->newInstance();
74+
}
75+
76+
return $attributeInstances;
77+
}
78+
}

‎src/Symfony/Bridge/PhpUnit/SymfonyExtension.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/SymfonyExtension.php
+8-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Bridge\PhpUnit\Extension\EnableClockMockSubscriber;
2121
use Symfony\Bridge\PhpUnit\Extension\RegisterClockMockSubscriber;
2222
use Symfony\Bridge\PhpUnit\Extension\RegisterDnsMockSubscriber;
23+
use Symfony\Bridge\PhpUnit\Metadata\AttributeReader;
2324
use Symfony\Component\ErrorHandler\DebugClassLoader;
2425

2526
class SymfonyExtension implements Extension
@@ -30,23 +31,25 @@ public function bootstrap(Configuration $configuration, Facade $facade, Paramete
3031
DebugClassLoader::enable();
3132
}
3233

34+
$reader = new AttributeReader();
35+
3336
if ($parameters->has('clock-mock-namespaces')) {
3437
foreach (explode(',', $parameters->get('clock-mock-namespaces')) as $namespace) {
3538
ClockMock::register($namespace.'\DummyClass');
3639
}
3740
}
3841

39-
$facade->registerSubscriber(new RegisterClockMockSubscriber());
40-
$facade->registerSubscriber(new EnableClockMockSubscriber());
41-
$facade->registerSubscriber(new DisableClockMockSubscriber());
42+
$facade->registerSubscriber(new RegisterClockMockSubscriber($reader));
43+
$facade->registerSubscriber(new EnableClockMockSubscriber($reader));
44+
$facade->registerSubscriber(new DisableClockMockSubscriber($reader));
4245

4346
if ($parameters->has('dns-mock-namespaces')) {
4447
foreach (explode(',', $parameters->get('dns-mock-namespaces')) as $namespace) {
4548
DnsMock::register($namespace.'\DummyClass');
4649
}
4750
}
4851

49-
$facade->registerSubscriber(new RegisterDnsMockSubscriber());
50-
$facade->registerSubscriber(new DisableDnsMockSubscriber());
52+
$facade->registerSubscriber(new RegisterDnsMockSubscriber($reader));
53+
$facade->registerSubscriber(new DisableDnsMockSubscriber($reader));
5154
}
5255
}

‎src/Symfony/Bridge/PhpUnit/Tests/Fixtures/symfonyextension/tests/bootstrap.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/PhpUnit/Tests/Fixtures/symfonyextension/tests/bootstrap.php
+3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@
2121
});
2222

2323
require __DIR__.'/../../../../SymfonyExtension.php';
24+
require __DIR__.'/../../../../Attribute/DnsSensitive.php';
25+
require __DIR__.'/../../../../Attribute/TimeSensitive.php';
2426
require __DIR__.'/../../../../Extension/DisableClockMockSubscriber.php';
2527
require __DIR__.'/../../../../Extension/DisableDnsMockSubscriber.php';
2628
require __DIR__.'/../../../../Extension/EnableClockMockSubscriber.php';
2729
require __DIR__.'/../../../../Extension/RegisterClockMockSubscriber.php';
2830
require __DIR__.'/../../../../Extension/RegisterDnsMockSubscriber.php';
31+
require __DIR__.'/../../../../Metadata/AttributeReader.php';
2932

3033
if (file_exists(__DIR__.'/../../../../vendor/autoload.php')) {
3134
require __DIR__.'/../../../../vendor/autoload.php';

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.