测试PHPSpec symfony登录用户

时间:2016-01-24 14:59:34

标签: symfony phpspec

我是使用PHPSpec测试PHP的新手。我有一个类,我注入symfony当前记录的用户(TokenStorageInterface)。并对该用户进行更改。

<?php

namespace AppBundle\Service;

use AppBundle\Entity\Payment;
use AppBundle\Entity\User;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class TransferService
{
    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * @var TokenStorageInterface
     */
    private $tokenStorage;

    /**
     * @var User
     */
    private $currentUser;

    /**
     * @var InvoiceService
     */
    private $invoiceService;

    /**
     * PaymentManager constructor.
     * @param EntityManager $entityManager
     * @param TokenStorageInterface $tokenStorage
     * @param InvoiceService $invoiceService
     */
    public function __construct(
        EntityManager $entityManager,
        TokenStorageInterface $tokenStorage,
        InvoiceService $invoiceService
    ) {
        $this->entityManager = $entityManager;

        if ($tokenStorage->getToken() === null) {
            throw new \Exception('User not logged in');
        }

        $this->currentUser = $tokenStorage->getToken()->getUser();
        $this->invoiceService = $invoiceService;
    }

    /**
     * @param Payment $payment
     */
    public function transfer(Payment $payment)
    {
        $payer    = $this->currentUser;
        $amount   = $payment->getAmount();
        $receiver = $payment->getReceiver();

        if ($payer === $receiver) {
            throw new \LogicException('Cannot be same User');
        }

        if ($payer->getBalance() < $amount) {
            throw new \LogicException('Not enough in balance');
        }

        $payment->setPayer($payer);

        //TODO: Move to class?
        $this->subtractBalance($payer, $amount);
        $this->addBalance($receiver, $amount);

        $this->invoiceService->createInvoice($payment);

        $this->entityManager->persist($payment);
        $this->entityManager->flush();
    }

    /**
     * @param User $user
     * @param $amount
     */
    private function subtractBalance(User $user, $amount)
    {
        $user->setBalance($user->getBalance() - $amount);
    }

    /**
     * @param User $user
     * @param $amount
     */
    private function addBalance(User $user, $amount)
    {
        $temp = $user->getBalance();
        $user->setBalance($user->getBalance() + $amount);
    }
}

并为该课程编写了Spec:

<?php

namespace spec\AppBundle\Service;

use AppBundle\Entity\Payment;
use AppBundle\Entity\User;
use AppBundle\Service\InvoiceService;
use Doctrine\ORM\EntityManager;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class TransferServiceSpec extends ObjectBehavior
{

    function let(EntityManager $entityManager, TokenStorage $tokenStorage, InvoiceService $invoiceService)
    {
        $user = new User();
        $user->setUsername('aaa');
        $user->setBalance(100.10);

        $temp = new UsernamePasswordToken($user, null, 'main', ['ROLE_USER']);
        $tokenStorage->getToken()->willReturn($temp);

        $this->beConstructedWith($entityManager, $tokenStorage, $invoiceService);
    }

    function it_is_initializable()
    {
        $this->shouldHaveType('AppBundle\Service\TransferService');
    }

    function it_should_transfer_money(
        User $user,
        EntityManager $entityManager,
        TokenStorageInterface $tokenStorage,
        InvoiceService $invoiceService,
        Payment $payment
    ) {
        $user->getBalance()->willReturn(0);
        $user->setBalance(99.9)->shouldBeCalled();

        $payment->getReceiver()->willReturn($user);
        //TODO how to check injected current user?
        //$payment->getPayer()->willReturn($tokenStorage->getToken());
        $payment->getAmount()->willReturn(99.9);

        $invoiceService->createInvoice($payment)->shouldBeCalled();

        $entityManager->persist($payment)->shouldBeCalled();
        $entityManager->flush()->shouldBeCalled();

        $this->transfer($payment);
    }

}

问题是,如何检查当前用户(注入令牌存储器getUser())是否进行了更改(以测试该天平已编辑),因为以下方法不起作用:

$payment->getPayer()->willReturn($tokenStorage->getToken()->getUser());

调用未定义的方法Prophecy \ Prophecy \ MethodProphecy :: getUser()

1 个答案:

答案 0 :(得分:2)

你不应该在预言中调用方法,而是模仿一切,参见:

function it_should_transfer_money(
   User $user,
   EntityManager $entityManager,
   TokenStorageInterface $tokenStorage,
   TokenInterface $token,
   UserInterface $user,
   InvoiceService $invoiceService,
   Payment $payment
) {
   $user->getBalance()->willReturn(0);
   $user->setBalance(99.9)->shouldBeCalled();

   $payment->getReceiver()->willReturn($user);
   $tokenStorage->getToken()->willReturn($token);
   $token->getUser()->willReturn($user);
   $payment->getPayer()->willReturn($user);
   $payment->getAmount()->willReturn(99.9);

   $invoiceService->createInvoice($payment)->shouldBeCalled();

   $entityManager->persist($payment)->shouldBeCalled();
   $entityManager->flush()->shouldBeCalled();

   $this->transfer($payment);
}