ServiceManager可以';使用phpunit进行测试时,无法通过完整命名空间查找类

ServiceManager可以';使用phpunit进行测试时,无法通过完整命名空间查找类,php,unit-testing,zend-framework2,servicemanager,Php,Unit Testing,Zend Framework2,Servicemanager,在某些情况下,我通过实例的全名从ServiceManager检索实例,例如: $someThing = $serviceManager->get('MyModule\Some\Nice\Lib\SomeThing'); 这对于HTTP MVC请求非常有效,但是,当使用phpunit时,ServiceManager找不到它。(它抛出一个Zend\ServiceManager\Exception\ServiceNotFoundException异常,消息为“Zend\ServiceManag

在某些情况下,我通过实例的全名从ServiceManager检索实例,例如:

$someThing = $serviceManager->get('MyModule\Some\Nice\Lib\SomeThing');
这对于HTTP MVC请求非常有效,但是,当使用phpunit时,ServiceManager找不到它。(它抛出一个
Zend\ServiceManager\Exception\ServiceNotFoundException
异常,消息为“
Zend\ServiceManager\ServiceManager::get
无法获取或创建…”的实例)

我使用的是来自的默认测试引导示例,我在不同mashine上的两个不同项目中遇到了这个问题,所以我想这是一个普遍的问题

我的第一个猜测是,它与MVC或应用程序有关,因为这很可能是测试和http之间唯一的真正区别。我甚至在两种模式下都转储了SM实例,并相互比较,查看源代码并搜索web

不幸的是,由于我的劳动合同,我无法粘贴任何代码。然而,正如我所说,我认为这是一个普遍的问题,所以你应该能够很容易地重现它


是否有人知道导致此问题的原因以及如何解决此问题?

请确保已将模块添加到测试配置:

return array(
    'modules' => array(
        'MyModule',
        //...
    ),
    //...
);

否则ModuleManager将不会尝试加载它,因此不会注册模块自动加载程序

我设法找到了问题所在

当您使用
ServiceManager
创建具有完整类名的实例时,默认情况下它实际上无法创建它。但是,如果可能的话,它会将任务委托给附加到它的抽象工厂

现在,当您使用DiFactory创建Di实例时,工厂会向SM注册一个
DiAbstractServiceFactory
。你猜,这个抽象工厂能够通过类的全名实例化类

我很少在这个项目中使用
Di
(因为我对它不太满意,一开始就用错了;我现在更清楚了),这就是为什么我实例化
Di
的唯一点是在模块的
onBootstrap()
方法内部。这在MVC上下文中很好,但是,由于
onBootstrap()
是一个HTTP MVC事件处理程序,因此在我的测试应用程序中不会调用它。因此,任何时候都不会实例化任何
Di
,因此,
ServiceManager
没有附加
DiAbstractServiceFactory
,因此它无法委托
get()
调用,因此它无法按类的全名实例化类

就这么简单!:-)


显而易见的解决方案是:在测试应用程序中创建一个
Di
实例。

加载模块,我还可以使用
new
关键字直接实例化它。那么,您的服务的配置可能是在应用程序级别配置中,而不是在测试期间加载的?您忘了在问题中提到最重要的部分:您使用的Zend\Di和SM只是一个代理:您可以共享示例代码吗。我也有同样的问题,无法克服。没有太多的示例代码可供共享。只需调用
$serviceManager->get('Di')某个地方。我已经基于此编写了代码。在这篇文章中,您能告诉我们在哪里以及所有的更改都必须完成,以便我们能够克服这个问题吗?我也是。只需将它放在始终执行它的某个地方(例如在Bootstrap.php中)。