我學習了TDD,並且我已經開始使用xSpec工具(語言無所謂,但在我的情況下,它是phpspec2)。我寫我的第一個規範:如何使用xSpec工具正確測試存儲庫?
<?php
namespace spec\Mo\SpeechBundle\Controller;
use Doctrine\Common\Collections\Collection;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
use Mo\SpeechBundle\Repository\IdeaRepository;
use Mo\SpeechBundle\Repository\SpeechRepository;
use Mo\SpeechBundle\Entity\Idea;
use Mo\SpeechBundle\Entity\Speech;
class SpeechControllerSpec extends ObjectBehavior
{
function let(SpeechRepository $speechRepository, IdeaRepository $ideaRepository, EngineInterface $templating)
{
$this->beConstructedWith($speechRepository, $ideaRepository, $templating);
}
function it_is_initializable()
{
$this->shouldHaveType('Mo\SpeechBundle\Controller\SpeechController');
}
function it_responds_to_show_action(EngineInterface $templating, Speech $speech, Response $response)
{
$templating
->renderResponse('MoSpeechBundle:Speech:show.html.twig', ['speech' => $speech])
->willReturn($response)
;
$this->showAction($speech)->shouldBeAnInstanceOf('Symfony\Component\HttpFoundation\Response');
}
function it_responds_to_list_action(
SpeechRepository $speechRepository,
IdeaRepository $ideaRepository,
EngineInterface $templating,
Response $response
)
{
$speeches = [new Speech()];
$ideas = [new Idea()];
$speechRepository->findAll()->willReturn($speeches);
$ideaRepository->findAll()->willReturn($ideas);
$templating
->renderResponse('MoSpeechBundle:Speech:list.html.twig', compact('speeches', 'ideas'))
->willReturn($response)
;
$this->listAction()->shouldBeAnInstanceOf('Symfony\Component\HttpFoundation\Response');
}
function it_responds_list_by_idea_action(
Idea $idea,
SpeechRepository $speechRepository,
IdeaRepository $ideaRepository,
EngineInterface $templating,
Response $response
)
{
$speeches = [new Speech()];
$ideas = [new Idea()];
$speechRepository->findByIdea($idea)->willReturn($speeches);
$ideaRepository->findAll()->willReturn($ideas);
$templating
->renderResponse('MoSpeechBundle:Speech:list.html.twig', compact('speeches', 'idea', 'ideas'))
->willReturn($response)
;
$this->listByIdeaAction($idea)->shouldBeAnInstanceOf('Symfony\Component\HttpFoundation\Response');
}
}
對於控制器:
<?php
namespace Mo\SpeechBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Mo\SpeechBundle\Repository\IdeaRepository;
use Mo\SpeechBundle\Repository\SpeechRepository;
use Mo\SpeechBundle\Entity\Idea;
use Mo\SpeechBundle\Entity\Speech;
/**
* Manages speeches.
*/
class SpeechController
{
/**
* @var \Mo\SpeechBundle\Repository\SpeechRepository
*/
private $speechRepository;
/**
* @var \Mo\SpeechBundle\Repository\IdeaRepository
*/
private $ideaRepository;
/**
* @var \Symfony\Bundle\FrameworkBundle\Templating\EngineInterface
*/
private $templating;
/**
* @param \Mo\SpeechBundle\Repository\SpeechRepository $speechRepository
* @param \Mo\SpeechBundle\Repository\IdeaRepository $ideaRepository
* @param \Symfony\Bundle\FrameworkBundle\Templating\EngineInterface $templating
*/
public function __construct(SpeechRepository $speechRepository, IdeaRepository $ideaRepository, EngineInterface $templating)
{
$this->speechRepository = $speechRepository;
$this->ideaRepository = $ideaRepository;
$this->templating = $templating;
}
/**
* Shows speech.
*
* @param \Mo\SpeechBundle\Entity\Speech $speech
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showAction(Speech $speech)
{
return $this->templating->renderResponse('MoSpeechBundle:Speech:show.html.twig', compact('speech'));
}
/**
* Shows list of speeches filtered by idea.
*
* @param \Mo\SpeechBundle\Entity\Idea $idea
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listByIdeaAction(Idea $idea)
{
$speeches = $this->speechRepository->findByIdea($idea);
$ideas = $this->ideaRepository->findAll();
return $this->templating->renderResponse('MoSpeechBundle:Speech:list.html.twig', compact('speeches', 'idea', 'ideas'));
}
/**
* Shows list of all speeches.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listAction()
{
$speeches = $this->speechRepository->findAll();
$ideas = $this->ideaRepository->findAll();
return $this->templating->renderResponse('MoSpeechBundle:Speech:list.html.twig', compact('speeches', 'ideas'));
}
}
好了,現在我敢肯定,指定我的控制器的這種行爲,我可以繼續前進。但我有另一個問題。
我使用存儲庫控制器規格的模擬,現在我想要寫規範的庫本身:
<?php
namespace Mo\SpeechBundle\Repository;
use Doctrine\ORM\EntityRepository;
use Mo\SpeechBundle\Entity\Idea;
class SpeechRepository extends EntityRepository
{
/**
* Finds all speeches by specified idea.
*
* @param \Mo\SpeechBundle\Entity\Idea $idea
*
* @return array
*/
public function findByIdea(Idea $idea)
{
return $this
->createQueryBuilder('s')
->leftJoin('s.ideas', 'i')
->where('i = :idea')
->setParameters(compact('idea'))
->getQuery()
->getResult()
;
}
}
但規格描述的行爲,我的理解。如何正確地測試存儲庫,以便真正地返回我需要的內容,在我的案例中由想法進行演講。
我應該考慮使用xUnit工具(PHPUnit在PHP世界)創建功能測試嗎?或者我寫 te spec描述了我的存儲庫正確地創建查詢?或者我可以只爲所有應用程序使用Behat,不要關注這個問題。
爲什麼當您在構造函數中使用DI時,您將庫傳遞給Controllerspec中的方法?你不能只調用「$ this-> repository」嗎? – user3746259