从 DI 容器获取服务是我的测试套件中的冒烟测试不可或缺的一部分。例如,以下测试确保容器中注册的服务的构建没有问题,并且这些服务不会花费太多时间来构建。
private const DEFAULT_TRESHOLD = 30;
public function testServicesLoadInTime()
{
$client = static::createClient();
/**
* Add serviceid as key, possible values:
* - false: Skip test for this service
* - integer value: Custom responsetime
*/
$customCriteria = [
// See: https://github.com/symfony/monolog-bundle/issues/192
'monolog.activation_strategy.not_found' => false,
'monolog.handler.fingers_crossed.error_level_activation_strategy' => false,
// Should not be used directly (Factories will inject other parameters)
'liip_imagine.binary.loader.prototype.filesystem' => false,
// Services that are allowed to load longer (Only for CLI tasks like workers)
'assetic.asset_manager' => 1000,
];
foreach ($client->getContainer()->getServiceIds() as $id) {
if (isset($customCriteria[$id]) && $customCriteria[$id] === false) {
continue;
}
try {
$startedAt = microtime(true);
$service = $client->getContainer()->get($id);
$elapsed = (microtime(true) - $startedAt) * 1000;
$this->assertNotNull($service);
$treshold = $customCriteria[$id] ?? self::DEFAULT_TRESHOLD;
$this->assertLessThan($treshold, $elapsed, sprintf(
'Service %s loaded in %d ms which is more than the %d ms threshold',
$id, $elapsed, $treshold
));
} catch (InactiveScopeException $e) {
// Noop
} catch (\Throwable $ex) {
$this->fail(sprintf("Fetching service %s failed: %s", $id, $ex->getMessage()));
}
}
}
然而。Symfony 第 4 版默认将服务私有化。get()
即将发布的 3.4 版将在服务未标记为公共时使用该方法从服务容器中获取服务时触发弃用警告。
这让我想知道是否有一种方法可以在不创建将所有服务作为构造函数参数的公共服务的情况下保持此冒烟测试运行,而容器中有近 1000 个服务当然不是一个可行的选择。