2

我有一个正在为其编写测试的新模块。该模块包含一个实现 ServiceLocatorAwareInterface 的类,因为它需要使用 DI 容器创建其他对象。在骨架应用程序中运行时一切正常,但在运行模块测试时,我得到以下信息:

Zend\Di\Exception\RuntimeException:“Zend\ServiceManager\ServiceLocatorInterface”的类型为“NULL”的无效实例化器

稍微研究一下,我发现 DI 容器试图创建一个“ServiceLocatorAwareInterface”类型的新对象,这当然是错误的。

在测试引导程序中进一步挖掘,我发现添加以下行可以解决问题,因为 DI 现在知道要为该接口实例化哪个类。

$di->instanceManager()->addTypePreference('Zend\ServiceManager\ServiceLocatorInterface', new \Zend\ServiceManager\ServiceManager());

我不确定这是否是问题的最佳解决方案,因为我传递的 ServiceManager 是一个虚拟的。

有没有人有任何其他想法?

4

2 回答 2

2

是的,你正朝着正确的方向前进。(请参阅首选项文档

现在没有多少人使用 DI 来支持 ServiceManager(包括我自己),但是如果 DI 的配置与 ZF2 beta 期间的配置保持相似,您应该能够在您的 DI 配置中添加“首选项”部分像这样:

'di' => array(
    'instance' => array(
        'preferences' => array(
            'My_Interface' => 'My_Implementation_Or_Alias',
        ) 
    )
)

此配置块可以替换您对$di->instanceManager()->addTypePreference()


查看当前文档,并模仿此处的示例,您可能会成功定义 DI 配置,如下所示使用 ZF2 官方版本:

$di = new Zend\Di\Di;
$di->configure(new Zend\Di\Config(array(
    'instance' => array(
        'preferences' => array(
            'My_Interface' => 'My_Implementation_Or_Alias',
        ) 
    )
)));
于 2012-09-17T20:37:01.577 回答
1

在这种情况下,您可以执行以下操作。

在模块单元测试的引导程序中,创建一个虚拟应用程序,该应用程序配置了仅加载您正在测试的模块的配置。

...//other code before this for autoloading stuff

// DON'T RUN THE application in your tests, just init it
$application = Zend\Mvc\Application::init(include 'config/test.application.config.for.module.php');

$fullyConfigedManager = $application->getServiceManager();

TestCases::setServiceManager( $fullyConfigedManager );

应用程序启动后,您可以直接从应用程序中拉取 ServiceManager。该服务管理器应该完全配置有任何工厂、可调用对象和模块中的配置。

于 2012-09-14T19:24:00.763 回答