我有一个新的模块,我正在编写测试。 该模块包含一个实现ServiceLocatorAwareInterface的类,因为它需要使用DI容器创建其他对象。在骨架应用程序中运行时,一切正常,但在运行模块测试时,我得到以下结果:
Zend \ Di \ Exception \ RuntimeException:“Zend \ ServiceManager \ ServiceLocatorInterface”类型为“NULL”的实例化器无效
稍微研究一下,我发现DI容器试图创建一个类型为“ServiceLocatorAwareInterface”的新对象,这当然是错误的。
在测试引导程序中再挖一点,我发现添加以下行解决了这个问题,因为DI现在知道要为该接口实例化的类。
$di->instanceManager()->addTypePreference('Zend\ServiceManager\ServiceLocatorInterface', new \Zend\ServiceManager\ServiceManager());
我不确定这是否是问题的最佳解决方案,因为我传递的ServiceManager是虚拟的。
有没有人有其他想法?
答案 0 :(得分:2)
是的,你正朝着正确的方向前进。 (见the preferences documentation)
目前没有多少人使用DI支持ServiceManager(包括我自己),但如果DI的配置与ZF2测试版的配置类似,您应该可以添加“首选项”部分您的DI配置如下:
'di' => array(
'instance' => array(
'preferences' => array(
'My_Interface' => 'My_Implementation_Or_Alias',
)
)
)
此配置块可以取代您对$di->instanceManager()->addTypePreference()
查看当前的文档,并模仿示例here,您可以使用ZF2官方发布版成功定义DI配置,如下所示:
$di = new Zend\Di\Di;
$di->configure(new Zend\Di\Config(array(
'instance' => array(
'preferences' => array(
'My_Interface' => 'My_Implementation_Or_Alias',
)
)
)));
答案 1 :(得分: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。此服务管理器应完全配置模块中的任何工厂,可调用组件和配置。