运行模块测试时,ServiceLocatorAwareInterface会混淆DI容器

时间:2012-09-14 14:40:24

标签: php dependency-injection zend-framework2

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

  

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

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

在测试引导程序中再挖一点,我发现添加以下行解决了这个问题,因为DI现在知道要为该接口实例化的类。

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

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

有没有人有其他想法?

2 个答案:

答案 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。此服务管理器应完全配置模块中的任何工厂,可调用组件和配置。