Skip to content

Commit 6640a79

Browse files
committed
test: test de la couche Container
1 parent e04a0b8 commit 6640a79

7 files changed

Lines changed: 1024 additions & 1 deletion

File tree

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Blitz PHP framework.
5+
*
6+
* (c) 2022 Dimitri Sitchet Tomkeu <devcode.dst@gmail.com>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
use BlitzPHP\Container\Container;
13+
use BlitzPHP\Container\AbstractProvider;
14+
use BlitzPHP\Spec\ReflectionHelper;
15+
use Kahlan\Plugin\Double;
16+
17+
use function Kahlan\expect;
18+
19+
describe('Container / AbstractProvider', function (): void {
20+
describe('Méthodes de base', function () {
21+
it('constructeur initialise le container', function () {
22+
$mockContainer = Double::instance(['class' => Container::class]);
23+
$provider = new class($mockContainer) extends AbstractProvider {};
24+
25+
$container = ReflectionHelper::getPrivateProperty($provider, 'container');
26+
27+
expect($container)->toBe($mockContainer);
28+
});
29+
30+
it('definitions retourne tableau vide par défaut', function () {
31+
$provider = new class(Double::instance(['class' => Container::class])) extends AbstractProvider {};
32+
33+
expect($provider::definitions())->toBe([]);
34+
});
35+
36+
it('register ne fait rien par défaut', function () {
37+
$provider = new class(Double::instance(['class' => Container::class])) extends AbstractProvider {};
38+
39+
expect(fn() => $provider->register())->not->toThrow();
40+
});
41+
42+
it('provides retourne les clés des définitions', function () {
43+
$provider = new class(Double::instance(['class' => Container::class])) extends AbstractProvider {
44+
public static function definitions(): array
45+
{
46+
return [
47+
'service.one' => fn() => 'one',
48+
'service.two' => fn() => 'two',
49+
];
50+
}
51+
};
52+
53+
expect($provider->provides())->toBe(['service.one', 'service.two']);
54+
});
55+
});
56+
});
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
<?php
2+
3+
/**
4+
* This file is part of Blitz PHP framework.
5+
*
6+
* (c) 2022 Dimitri Sitchet Tomkeu <devcode.dst@gmail.com>
7+
*
8+
* For the full copyright and license information, please view
9+
* the LICENSE file that was distributed with this source code.
10+
*/
11+
12+
use BlitzPHP\Container\BaseServices;
13+
use BlitzPHP\Contracts\Autoloader\LocatorInterface;
14+
use BlitzPHP\Http\Request;
15+
use BlitzPHP\Http\UrlGenerator;
16+
use BlitzPHP\Spec\ReflectionHelper;
17+
use DI\NotFoundException;
18+
use Psr\Http\Message\ServerRequestInterface;
19+
20+
use function Kahlan\expect;
21+
22+
describe('Container / BaseServices', function (): void {
23+
beforeAll(function () {
24+
$this->baseInstances = ReflectionHelper::getPrivateProperty(BaseServices::class, 'instances');
25+
});
26+
27+
beforeEach(function () {
28+
// BaseServices::reset(true);
29+
BaseServices::resetSingle('test');
30+
});
31+
32+
afterEach(function () {
33+
ReflectionHelper::setPrivateProperty(
34+
BaseServices::class,
35+
'instances',
36+
$this->baseInstances
37+
);
38+
// BaseServices::reset(true);
39+
});
40+
41+
describe('Méthodes statiques de base', function () {
42+
it('autoloader retourne une instance', function () {
43+
$autoloader = BaseServices::autoloader(false);
44+
expect($autoloader)->toBeAnInstanceOf('BlitzPHP\Autoloader\Autoloader');
45+
});
46+
47+
it('autoloader partagé retourne même instance', function () {
48+
$autoloader1 = BaseServices::autoloader(true);
49+
$autoloader2 = BaseServices::autoloader(true);
50+
expect($autoloader1)->toBe($autoloader2);
51+
});
52+
53+
it('locator retourne une instance', function () {
54+
$locator = BaseServices::locator(false);
55+
expect($locator)->toBeAnInstanceOf(LocatorInterface::class);
56+
});
57+
58+
it('locator partagé retourne même instance', function () {
59+
$locator1 = BaseServices::locator(true);
60+
$locator2 = BaseServices::locator(true);
61+
expect($locator1)->toBe($locator2);
62+
});
63+
64+
xit('locator avec cache si configuré', function () {
65+
$initial = config()->get('optimize.locator_cache_enabled');
66+
BaseServices::resetSingle('locator');
67+
68+
$locator = BaseServices::locator(true);
69+
expect($locator)->toBeAnInstanceOf('BlitzPHP\Autoloader\LocatorCached');
70+
71+
config()->set('optimize.locator_cache_enabled', $initial);
72+
BaseServices::resetSingle('locator');
73+
});
74+
});
75+
76+
describe('Gestion des instances', function () {
77+
it('get leve une exception si non trouvé', function () {
78+
expect(fn() => BaseServices::get('inexistant'))->toThrow(new DI\NotFoundException());
79+
});
80+
81+
it('set définit une entrée', function () {
82+
$obj = new stdClass();
83+
$obj->name = 'test';
84+
BaseServices::set('test', $obj);
85+
expect(BaseServices::get('test'))->toBe($obj);
86+
});
87+
88+
it('set échoue si déjà défini', function () {
89+
$obj1 = new stdClass();
90+
$obj2 = new stdClass();
91+
BaseServices::set('test', $obj1);
92+
expect(fn() => BaseServices::set('test', $obj2))
93+
->toThrow(new InvalidArgumentException("L'entrée pour 'test' est déjà définie."));
94+
});
95+
96+
it('override remplace une entrée existante', function () {
97+
$obj1 = new stdClass();
98+
$obj1->name = 'old';
99+
$obj2 = new stdClass();
100+
$obj2->name = 'new';
101+
102+
BaseServices::set('test', $obj1);
103+
BaseServices::override('test', $obj2);
104+
105+
expect(BaseServices::get('test'))->toBe($obj2);
106+
expect(BaseServices::get('test')->name)->toBe('new');
107+
});
108+
109+
it('singleton crée et retourne une même instance', function () {
110+
$instance1 = BaseServices::singleton('test');
111+
$instance2 = BaseServices::singleton('test');
112+
expect($instance1)->toBe($instance2);
113+
});
114+
115+
it('singleton avec arguments', function () {
116+
$instance = BaseServices::singleton('request');
117+
expect($instance)->toBeAnInstanceOf(Request::class);
118+
});
119+
120+
it('factory crée nouvelle instance', function () {
121+
$generator1 = BaseServices::factory(UrlGenerator::class);
122+
$generator2 = BaseServices::factory(UrlGenerator::class);
123+
expect($generator1)->not->toBe($generator2);
124+
expect($generator1)->toBeAnInstanceOf(UrlGenerator::class);
125+
expect($generator2)->toBeAnInstanceOf(UrlGenerator::class);
126+
});
127+
});
128+
129+
describe('Gestion des mocks et reset', function () {
130+
it('injectMock définit un mock', function () {
131+
$mock = new stdClass();
132+
$mock->id = 'mock';
133+
BaseServices::injectMock('test', $mock);
134+
expect(BaseServices::get('test'))->toBe($mock);
135+
});
136+
137+
it('sharedInstance retourne mock si présent', function () {
138+
$mock = new stdClass();
139+
$mock->name = 'mock';
140+
BaseServices::injectMock('request', $mock);
141+
142+
$result = BaseServices::sharedInstance('request');
143+
expect($result)->toBe($mock);
144+
145+
BaseServices::resetSingle('request');
146+
});
147+
148+
it('resetSingle réinitialise un service spécifique', function () {
149+
$obj1 = new stdClass();
150+
$obj2 = new stdClass();
151+
152+
BaseServices::set('service1', $obj1);
153+
BaseServices::set('service2', $obj2);
154+
155+
BaseServices::resetSingle('service1');
156+
157+
expect(BaseServices::get('service2'))->toBe($obj2);
158+
expect(fn() => BaseServices::get('service1'))->toThrow(new NotFoundException());
159+
});
160+
});
161+
162+
describe('Découverte des services', function () {
163+
it('serviceExists trouve un service existant', function () {
164+
$result = BaseServices::serviceExists('httpclient');
165+
expect($result)->toBe('BlitzPHP\HttpClient\Config\Services');
166+
});
167+
168+
it('serviceExists retourne null pour service inexistant', function () {
169+
$result = BaseServices::serviceExists('inexistant');
170+
expect($result)->toBeNull();
171+
});
172+
173+
it('__callStatic appelle méthode de service', function () {
174+
$request = BaseServices::request();
175+
expect($request)->toBeAnInstanceOf(Request::class);
176+
});
177+
178+
it('__callStatic gère les factories', function () {
179+
$request = BaseServices::request(false);
180+
expect($request)->toBeAnInstanceOf(Request::class);
181+
});
182+
183+
it('__callStatic gère les singletons via discoverServices', function () {
184+
$request = BaseServices::request(true);
185+
expect($request)->toBeAnInstanceOf(Request::class);
186+
});
187+
});
188+
189+
describe('Alias et noms de service', function () {
190+
it('serviceName normalise via alias', function () {
191+
$method = new ReflectionMethod(BaseServices::class, 'serviceName');
192+
$method->setAccessible(true);
193+
194+
expect($method->invoke(null, 'locator'))->toBe('locator');
195+
expect($method->invoke(null, LocatorInterface::class))->toBe('locator');
196+
expect($method->invoke(null, 'request'))->toBe('request');
197+
expect($method->invoke(null, ServerRequestInterface::class))->toBe('request');
198+
});
199+
200+
it('serviceName retourne nom original si pas d\'alias', function () {
201+
$method = new ReflectionMethod(BaseServices::class, 'serviceName');
202+
$method->setAccessible(true);
203+
204+
expect($method->invoke(null, 'custom'))->toBe('custom');
205+
});
206+
});
207+
208+
describe('cacheServices', function () {
209+
it('cacheServices découvre et cache les services', function () {
210+
$cacheService = ReflectionHelper::getPrivateMethodInvoker(BaseServices::class,'cacheServices');
211+
ReflectionHelper::setPrivateProperty(BaseServices::class, 'discovered', false);
212+
213+
$cacheService();
214+
215+
expect(ReflectionHelper::getPrivateProperty(BaseServices::class, 'discovered'))->toBeTruthy();
216+
});
217+
218+
it('cacheServices ne fait rien si déjà découvert', function () {
219+
$cacheService = ReflectionHelper::getPrivateMethodInvoker(BaseServices::class,'cacheServices');
220+
ReflectionHelper::setPrivateProperty(BaseServices::class, 'discovered', true);
221+
222+
$cacheService();
223+
224+
expect(ReflectionHelper::getPrivateProperty(BaseServices::class, 'discovered'))->toBeTruthy();
225+
});
226+
});
227+
});

0 commit comments

Comments
 (0)