drema2014 2012-12-10 11:13
浏览 76
已采纳

单元测试Symfony2

I am trying to use Mockery in order to unit test my sf2 functions. 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:

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

Mockery\Exception: The method isGranted is marked final and it is not possible to generate a mock object with such a method defined. You should instead pass an instance of this object to Mockery to create a partial mock.

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

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

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

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

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

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

I really would appreciate some help before I end-up with 100 lines test to test a 8 lines function...

  • 写回答

1条回答 默认 最新

  • dongqucheng3851 2012-12-10 14:29
    关注

    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.

    If MenuBuilder is a custom class, it should use the interface too rather than the actual implementation.

    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);
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog
  • ¥15 Excel发现不可读取的内容