如何模拟ServiceLocator ZF2


How to mock ServiceLocator ZF2?

这是一个工厂:

namespace Maintenance'Factory'View'Helper;
use Zend'ServiceManager'FactoryInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
use Maintenance'View'Helper'SousMenuContrat;
class SousMenuContratFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator)
        {
            $realServiceLocator = $serviceLocator->getServiceLocator();
            $maiContratService = $realServiceLocator->get(
                'Maintenance'Service'Model'FMaiContratService'
            );   
            return new SousMenuContrat(
                $maiContratService
            );
        }
   } 

我必须写一些PHPUnit测试,我开始这样做:

public function testCreateService()
    {
        $this->mockDriver = $this->getMock('Zend'Db'Adapter'Driver'DriverInterface');
        $this->mockConnection = $this->getMock('Zend'Db'Adapter'Driver'ConnectionInterface');
        $this->mockDriver->expects($this->any())->method('checkEnvironment')->will($this->returnValue(true));
        $this->mockDriver->expects($this->any())->method('getConnection')->will($this->returnValue($this->mockConnection));
        $this->mockPlatform = $this->getMock('Zend'Db'Adapter'Platform'PlatformInterface');
        $this->mockStatement = $this->getMock('Zend'Db'Adapter'Driver'StatementInterface');
        $this->mockDriver->expects($this->any())->method('createStatement')->will($this->returnValue($this->mockStatement));
        $this->adapter = new Adapter($this->mockDriver, $this->mockPlatform);
        $this->sql = new Sql($this->adapter);

        $mockTableGateway = $this->getMock('Zend'Db'TableGateway'TableGateway', array(), array(), '', false);
        $maiContratTable = $this->getMockBuilder('Maintenance'Model'BDD'FMaiContratTable')
            ->setMethods(array())
            ->setConstructorArgs(array($mockTableGateway, $this->adapter, $this->sql))
            ->getMock();

        $smMock = $this->getMockBuilder('Zend'ServiceManager'ServiceManager')
                       ->setMethods(array('get'))
                       ->getMock();
        $smMock->expects($this->at(0))
            ->method('get')
            ->with('Maintenance'Service'Model'FMaiContratService')
            ->will($this->returnValue(new FMaiContratService($maiContratTable)));
        $factory = new SousMenuContratFactory();
        $runner = $factory->createService($smMock);
    }

但是我遇到了一些问题。这告诉我:

调用未定义方法Mock_ServiceManager_3ed93deb::getServiceLocator()

我误解了什么?

谢谢!

在您的工厂中,您调用:

$realServiceLocator = $serviceLocator->getServiceLocator();

但是你定义了:

$smMock->expects($this->at(0))
        ->method('get')

传递给工厂的ServiceLocator通常没有方法getServiceLocator,因为它已经是服务定位器。(编辑:划痕,PluginManagers做!)而是使用:

public function createService(ServiceLocatorInterface $serviceLocator)
{
    $maiContratService = $serviceLocator->get(
        'Maintenance'Service'Model'FMaiContratService'
    );   
    return new SousMenuContrat(
        $maiContratService
    );
}

编辑:插件工厂是另一回事,这里是测试代码:

public function testCreateService()
{
    $maiContractServiceMock = $this->getMockBuilder('Maintenance'Service'Model'FMaiContratService')
        ->disableOriginalConstructor()
        ->getMock();
    // if you do something with FMaiContratService in the constructor of SousMenuContrat,
    // mock more methods here
    $smMock = $this->getMockBuilder('Zend'ServiceManager'ServiceManager')
        ->setMethods(array('get'))
        ->getMock();
    $smMock->expects($this->at(0))
        ->method('get')
        ->with('Maintenance'Service'Model'FMaiContratService')
        ->will($this->returnValue($maiContractServiceMock));
    $hpmMock = $this->getMockBuilder('Zend'View'HelperPluginManager')
        ->setMethods(array('getServiceLocator'))
        ->getMock();
    $hpmMock->expects($this->any())
        ->method('getServiceLocator')
        ->will($this->returnValue($smMock));
    $factory = new SousMenuContratFactory();
    $runner = $factory->createService($hpmMock);
}

在这种情况下,您需要模拟插件管理器,在调用getServiceLocator时返回另一个服务定位器。抱歉,!