我正在尝试使用Mockery来对我的sf2功能进行单元测试。 我对我的第一次尝试感到不安。
首先尝试测试使用安全上下文的类:
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();
}
}
我创建了一个 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);
}
运行单元测试时,收到错误:
testsetSecurityContext
Mockery \ Exception:方法isGranted标记为final,并且无法生成定义了此类方法的模拟对象。您应该将此对象的实例传递给Mockery以创建部分模拟。
所以我相应地改变了我的测试功能:
public function testsetSecurityContext()
{
/* @var $securityContext SecurityContext */
$securityContext = m::mock(new \Symfony\Component\Security\Core\SecurityContext());
/* ... skipped ... */
}
现在我收到了这个错误:
testsetSecurityContext
ErrorException:Catchable Fatal Error:传递给Symfony \ Component \ Security \ Core \ SecurityContext :: __ construct()的参数1必须实现接口 Symfony \ Component \ Security \ Core \ Authentication \ AuthenticationManagerInterface ,none给定,在第91行的..MenuBuilderTest.php中调用,并在..Symfony \ Component \ Security \ Core \ SecurityContext.php第41行中定义
所以我再次修改我的代码:
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 ... */
}
我得到另一个错误:
testsetSecurityContext
ErrorException:Catchable Fatal Error:传递给Symfony \ Component \ Security \ Core \ SecurityContext :: __ construct()的参数2必须实现接口 Symfony \ Component \ Security \ Core \ Authorization \ AccessDecisionManagerInterface ,none给定,在第94行的... \ MenuBuilderTest.php中调用,并在... \ Symfony \ Component \ Security \ Core \ SecurityContext.php第41行中定义
我最终得到:
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);
}
这仍然不行,因为我收到了这个错误:
testsetSecurityContext
ErrorException:Catchable Fatal Error:传递给Atos \ Worldline \ Fm \ Integration \ Ucs \ EventFlowAnalyser \ Menu \ MenuBuilder :: setSecurityContext()的参数1必须是 Symfony \ Component \ Security \ Core \ SecurityContext的实例,给出了 Mockery_50c5c1e0e68d2 的实例,在第106行的.. \ MenuBuilderTest.php中调用,并在.. \ MenuBuilder.php第140行中定义
在最终用100线测试来测试8线功能之前,我真的很感激一些帮助......
答案 0 :(得分:5)
不是模拟实例,而是去实现它实现的接口。它几乎总能更好地工作,几乎Symfony2中的所有内容都有明确定义的接口。
如果MenuBuilder是一个自定义类,它应该使用接口而不是实际的实现。
的Symfony \元器件\安全\核心\ 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);
}