ZF2 - Module.php中请求的模拟服务

mar*_*osh 36 php testing phpunit zend-framework2

我正在尝试测试我的ZF2应用程序的控制器.假设这个控制器在我的A模块中.

在模块的onBootstrap方法中,我使用服务管理器来检索另一个模块的服务,比如说我没有加载.Module.phpAB

如何在服务管理器中设置所请求服务的模拟?请注意,我不能$this->getApplicationServiceLocator()在测试中使用它,因为这已经调用了Module.onBootstrap我的A模块的方法.

要发布一些代码,这就是我现在正在做的事情

bootstrap.php中

namespace Application;

use Zend\Mvc\Service\ServiceManagerConfig;
use Zend\ServiceManager\ServiceManager;
use RuntimeException;

class Bootstrap
{
    protected static $serviceManager;

    public static function init()
    {
        $modulePath = static::findParentPath('module');
        $vendorPath = static::findParentPath('vendor');

        if (is_readable($vendorPath . '/autoload.php')) {
            $loader = include $vendorPath . '/autoload.php';
        } else {
            throw new RuntimeException('Cannot locate autoload.php');
        }

        $config = [
            'modules' => [
                'Application',
            ],
            'module_listener_options' => [
                'module_paths' => [
                    $modulePath,
                    $vendorPath
                ]
            ]
        ];

        $serviceManager = new ServiceManager(new ServiceManagerConfig());
        $serviceManager->setService('ApplicationConfig', $config);
        $serviceManager->get('ModuleManager')->loadModules();
        static::$serviceManager = $serviceManager;
    }

    protected static function findParentPath($path)
    {
        $dir = __DIR__;
        $previousDir = '.';
        while (!is_dir($dir . '/' . $path)) {
            $dir = dirname($dir);
            if ($previousDir === $dir) {
                return false;
            }
            $previousDir = $dir;
        }
        return $dir . '/' . $path;
    }

    public static function getServiceManager()
    {
        return static::$serviceManager;
    }
}

Bootstrap::init();
Run Code Online (Sandbox Code Playgroud)

我的实际考试班

namespace Application\Functional;

use Application\Bootstrap;

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;

class ValidateCustomerRegistrationTest extends AbstractHttpControllerTestCase
{
    public function setUp()
    {
        $serviceManager = Bootstrap::getServiceManager();
        $applicationConfig = $serviceManager->get('ApplicationConfig');

        $this->setApplicationConfig($applicationConfig);
        parent::setUp();
    }

    public function testRegisterValidUserWithOnlyEquomobiliData()
    {
        $this->getApplicationServiceLocator();
    }
}
Run Code Online (Sandbox Code Playgroud)

Module.php简化了

namespace Application

Class Module
{
    public function onBootstrap(MvcEvent $e)
    {
        $serviceManager = $e->getApplication()->getServiceManager();
        $service = $serviceManager->get('Service\From\Other\Module');
    }
}
Run Code Online (Sandbox Code Playgroud)

Har*_*ood 1

这里没有足够的数据来直接帮助您。对于初学者来说如果有这个功能会更有用ValidateCustomerRegistrationTest->getApplicationServiceLocator()

我希望我能间接地帮助你。

重构可能会有所帮助

当我编写单元测试时,我从一些个人规则开始。

仅测试正在测试的代码。嘲笑其他一切。无需测试应该已经有自己的测试的东西。

函数如何工作并不重要。仅输入/输出。即使函数的核心发生了巨大变化,这也能让您的测试保持可行。

/**
 * @param MvcEventInterface $event
 * @param Service\From\Other\ModuleInterface $service
 *
 * @return boolean
 */
public function onBootstrap(MvcEventInterface $event, Service\From\Other\ModuleInterface $service)
{
  return true;
}
Run Code Online (Sandbox Code Playgroud)

然后在测试类中:

public function testOnBootstrap(){
   $eventMock = $this->getMock(MvcEventInterface::class);
   $serviceMock = $this->getMock(ModuleInterface::class);
   $module = new Module();

   $result = $module->onBootstrap($eventMock, $serviceMock);
   $this->assertTrue($result);
}
Run Code Online (Sandbox Code Playgroud)

* 我显然不知道你想测试什么

当重构不可行时

我立刻想到了两种可以提供帮助的模拟类型:mock 和mockBuilder。查看PHPUnit 文档中的 Test Doubles

$serviceMock = $this->getMockBuilder(ServiceManager::class)
    ->disableOriginalConstructor()
    ->setMethods([
        '__construct',
        'get'
    ])
    ->getMock();

$serviceMock
    ->expects($this->any())
    ->method('get')
    ->will($this->returnValue(
        $this->getMock(ModuleManagerInterface::class)
    ));
Run Code Online (Sandbox Code Playgroud)

祝您好运,希望您能告诉我们是否可以更具体地帮助您。我还建议研究面向对象编程的 SOLID 原则。众多编程原则之一应该使您的代码干净、易于扩展且易于测试。