简体   繁体   English

单元测试Symfony2

[英]Unit Test Symfony2

I am trying to use Mockery in order to unit test my sf2 functions. 我正在尝试使用Mockery来对我的sf2函数进行单元测试。 I am strugeling with my first attempt. 我正在为第一次尝试而苦苦挣扎。

First try at test a class which uses security context: 首先尝试测试使用安全上下文的类:

public function setSecurityContext(SecurityContext $securityContext)
{
    $this->securityContext = $securityContext;
    try {
        $this->isLoggedIn = $securityContext->isGranted('IS_AUTHENTICATED_FULLY');
        $this->user = $securityContext->getToken()->getUser();
    } catch (\Exception $e) {
        $this->isLoggedIn = false;
        $this->user = $securityContext->getToken()->getUser();
    }
}

I create a testsetSecurityContext function like this: 我创建了一个testsetSecurityContext函数,如下所示:

public function testsetSecurityContext()
{
    /* @var $securityContext SecurityContext */
    $securityContext = m::mock('Symfony\Component\Security\Core\SecurityContext');

    $securityContext->shouldReceive('isGranted')
    ->with('IS_AUTHENTICATED_FULLY')
    ->once()
    ->andReturn(true);

    $factory = m::mock('Knp\Menu\FactoryInterface');

    $menu = new MenuBuilder($factory);

    $menu->setSecurityContext($securityContext);
}

When running unit test, I receive the error: 运行单元测试时,我收到错误消息:

testsetSecurityContext testsetSecurityContext

Mockery\\Exception: The method isGranted is marked final and it is not possible to generate a mock object with such a method defined. Mockery \\ Exception:方法isGranted被标记为final,并且无法使用定义的方法生成模拟对象。 You should instead pass an instance of this object to Mockery to create a partial mock. 相反,您应该将此对象的实例传递给Mockery以创建部分模拟。

So I change my test function accordingly: 因此,我相应地更改了测试功能:

public function testsetSecurityContext()
{
    /* @var $securityContext SecurityContext */
    $securityContext = m::mock(new \Symfony\Component\Security\Core\SecurityContext());
    /* ... skipped ... */
}

Now I receive that error: 现在,我收到该错误:

testsetSecurityContext testsetSecurityContext

ErrorException: Catchable Fatal Error: Argument 1 passed to Symfony\\Component\\Security\\Core\\SecurityContext::__construct() must implement interface Symfony\\Component\\Security\\Core\\Authentication\\AuthenticationManagerInterface , none given, called in ..MenuBuilderTest.php on line 91 and defined in ..Symfony\\Component\\Security\\Core\\SecurityContext.php line 41 ErrorException:可捕获的致命错误:传递给Symfony \\ Component \\ Security \\ Core \\ SecurityContext :: __ construct()的参数1必须实现Symfony \\ Component \\ Security \\ Core \\ Authentication \\ AuthenticationManagerInterface接口 ,未给出,在..MenuBuilderTest.php上调用第91行,并在..Symfony \\ Component \\ Security \\ Core \\ SecurityContext.php第41行中定义

So I modify my code again: 所以我再次修改我的代码:

public function testsetSecurityContext()
{

    $auth = m::mock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');

    /* @var $securityContext SecurityContext */
    $securityContext = m::mock(new \Symfony\Component\Security\Core\SecurityContext($auth));

    /* ... skipped ... */

}

And I get another error: 我得到另一个错误:

testsetSecurityContext testsetSecurityContext

ErrorException: Catchable Fatal Error: Argument 2 passed to Symfony\\Component\\Security\\Core\\SecurityContext::__construct() must implement interface Symfony\\Component\\Security\\Core\\Authorization\\AccessDecisionManagerInterface , none given, called in ...\\MenuBuilderTest.php on line 94 and defined in ...\\Symfony\\Component\\Security\\Core\\SecurityContext.php line 41 ErrorException:可捕获的致命错误:传递给Symfony \\ Component \\ Security \\ Core \\ SecurityContext :: __ construct()的参数2必须实现Symfony \\ Component \\ Security \\ Core \\ Authorization \\ AccessDecisionManagerInterface接口 ,未给出,在... \\ MenuBuilderTest中调用。第94行的php,并在... \\ Symfony \\ Component \\ Security \\ Core \\ SecurityContext.php第41行中定义

I endup with: 我最终得到:

public function testsetSecurityContext()
{

    $am = m::mock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
    $adm = m::mock('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface');

    /* @var $securityContext SecurityContext */
    $securityContext = m::mock(new \Symfony\Component\Security\Core\SecurityContext($am, $adm));

    $securityContext->shouldReceive('isGranted')
    ->with('IS_AUTHENTICATED_FULLY')
    ->once()
    ->andReturn(true);

    $factory = m::mock('Knp\Menu\FactoryInterface');

    $menu = new MenuBuilder($factory);

    $menu->setSecurityContext($securityContext);
}

And that is still not OK as I get that error: 而且仍然无法确定,因为我收到了该错误:

testsetSecurityContext testsetSecurityContext

ErrorException: Catchable Fatal Error: Argument 1 passed to Atos\\Worldline\\Fm\\Integration\\Ucs\\EventFlowAnalyser\\Menu\\MenuBuilder::setSecurityContext() must be an instance of Symfony\\Component\\Security\\Core\\SecurityContext , instance of Mockery_50c5c1e0e68d2 given, called in ..\\MenuBuilderTest.php on line 106 and defined in ..\\MenuBuilder.php line 140 ErrorException:可捕获的致命错误:传递给Atos \\ Worldline \\ Fm \\ Integration \\ Ucs \\ EventFlowAnalyser \\ Menu \\ MenuBuilder :: setSecurityContext()的参数1必须是Symfony \\ Component \\ Security \\ Core \\ SecurityContext的实例,给定的Mockery_50c5c1e0e68d2实例,在第106行的.. \\ MenuBuilderTest.php中调用,并在第140行的.. \\ MenuBuilder.php中定义

I really would appreciate some help before I end-up with 100 lines test to test a 8 lines function... 在完成100行测试以测试8行功能之前,我真的很感谢您的帮助。

Instead of mocking the instance, go for the interface it implements. 与其模拟实例,不如寻找它实现的接口。 It almost always works better and nearly everything in Symfony2 has well defined interfaces. 它几乎总是可以更好地工作,而且Symfony2中的几乎所有内容都具有定义明确的接口。

If MenuBuilder is a custom class, it should use the interface too rather than the actual implementation. 如果MenuBuilder是一个自定义类,则它也应该使用该接口,而不是实际的实现。

Symfony\\Component\\Security\\Core\\SecurityContextInterface Symfony \\ Component \\ Security \\ Core \\ SecurityContextInterface

public function testsetSecurityContext()
{
    /* @var $securityContext SecurityContext */
    $securityContext = m::mock('Symfony\Component\Security\Core\SecurityContextInterface');

    $securityContext->shouldReceive('isGranted')
    ->with('IS_AUTHENTICATED_FULLY')
    ->once()
    ->andReturn(true);

    $factory = m::mock('Knp\Menu\FactoryInterface');

    $menu = new MenuBuilder($factory);

    $menu->setSecurityContext($securityContext);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM