我目前正在为我的应用程序创建单元测试,但这是我第一次这样做。
我想测试这个功能:
/**
* This method search if the user is already in a team for the same tournament than the one passed in argument
* @param User $user
* @param Team $team
* @return bool|Team|mixed
*/
public function isAlreadyApplicant($user, Team $team) {
if (!$user || !$this->authorizationChecker->isGranted("ROLE_USER")) {
return false;
}
foreach ($user->getApplications() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getTeams() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
foreach ($user->getManagedTeam() as $userTeam) {
/** @var Team $userTeam */
if ($userTeam->getTournament()->getId() === $team->getTournament()->getId()) {
return $userTeam;
}
}
return false;
}
如您所见,第一个测试是检查用户是否拥有ROLE_USER。
当我尝试"记录我的用户"时,我收到此消息:
致命错误:在第56行的\ vendor \ symfony \ symfony \ src \ Symfony \ Component \ Security \ Core \ Authorization \ AuthorizationChecker.php中调用null上的成员函数getToken()
我尝试了在Symfony doc中找到的东西,但我必须错过一些东西。这是我的测试类:
class ApplicationCheckerTest extends WebTestCase
{
protected $client = null;
public function setUp() {
$this->client = static::createClient();
/** @var User $user */
$user = $this->client->getContainer()->get('doctrine')->getManager()->getRepository('MGDUserBundle:User')->findOneBy(array("email" => 'Player11.Player11@test.com'));
$this->loginUser("main", $user);
}
protected function loginUser($firewallName, UserInterface $user, array $options = array(), array $server = array())
{
$this->client = static::createClient();
$token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles());
static::$kernel->getContainer()->get('security.token_storage')->setToken($token);
$session = $this->client->getContainer()->get('session');
$session->set('_security_'.$firewallName, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
public function testIsAlreadyApplicantIsNotConnected()
{
$user = new User();
$team = new Team();
$router = $this->createMock(Router::class);
$authorizationChecker = $this->createMock(AuthorizationChecker::class);
$applicationChecker = new ApplicationChecker($router, $authorizationChecker);
$applicationChecker->isAlreadyApplicant($user, $team);
}
}
我的security.yml看起来像:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
target: /
remember_me:
secret: '%secret%'
我尝试将我创建的用户与灯具连接起来。
我不确定我尝试这样做的方式,也许我走错了路,如果我错了,请不要犹豫纠正我!
有关信息,请参阅Symfony 3.2.13
度过美好的一天
答案 0 :(得分:1)
您正在使用的WebTestCase
和Symfony文档中的示例应该用于控制器的功能测试。
您为客户端设置身份验证的方式是正确。但是您没有使用该客户端在测试用例中向引导的Symfony内核发出请求。您只是在手动创建的服务实例上进行简单的单元测试,这很好。
您只需使用PHPUnit\Framework\TestCase
即可。
可以使用WebTestCase
来测试您的服务,并覆盖内核容器中TokenStorage
而不是客户端容器中使用的AuthorizationChecker
,然后再获取来自内核容器的服务,而不是自己实例化它。但我没有看到它带来太多好处。无需测试Symfony组件(如果isGranted正在运行)。这属于Symfony项目的范围,很可能已经涵盖在那里。
您的错误原因是,无法模拟最终方法。作为一种解决方法,您可以将ApplicationChecker
构造函数中的依赖项设置为AuthorizationCheckerInterface
,然后在测试中从界面创建模拟。
$authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class);
$authorizationChecker->method('isGranted')->willReturn(true);