首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用xSpec工具正确地测试存储库?

如何使用xSpec工具正确地测试存储库?
EN

Stack Overflow用户
提问于 2014-01-31 00:08:40
回答 2查看 825关注 0票数 1

我学习了TDD,并且我已经开始使用xSpec工具(语言并不重要,但在我的例子中它是phpspec2 )。我编写了我的第一个规范:

代码语言:javascript
复制
<?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');
    }
}

主计长:

代码语言:javascript
复制
<?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'));
    }
}

好的,现在我确定我的控制器的行为是指定的,我可以继续前进。但我有另一个问题。

我在控制器规范中使用了模拟存储库,现在我想为存储库本身编写规范:

代码语言:javascript
复制
<?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工具( PHP中的PHPUnit)创建功能测试?还是描述我的存储库正确创建查询的wri te规范?或者我可以使用Behat对所有的应用程序,不要注意这个问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-13 20:04:29

我花了一周的时间来分析这个问题,并找到了令人满意的答案。

phpspec只指定对象的行为。没别的了。我们不能用它们创建功能测试。

因此,我们有两种方法来测试我们的功能:

  1. 使用PHPUnit编写模块和系统本身的功能测试。
  2. 使用Behat来描述我们应用程序的特性。

PHPUnit、其他类似的框架和Behat都有它们的缺陷和强大的一面。

使用什么,只能决定一个开发人员。

票数 2
EN

Stack Overflow用户

发布于 2014-02-09 21:03:45

我完全理解你的困境,我过去也做过同样的事情。我认为您的问题的基本答案是您的业务逻辑应该与任何框架(基础结构代码)分开,因此您不应该测试'Doctrine\ORM\EntityRepository‘类型的对象。

我认为最好的方法是在您的应用程序中有另一个层来保存您的业务逻辑,这反过来可以使用适配器从'Doctrine\ORM\EntityRepository‘类型对象来回传递消息。这样,您就可以完全说明您的业务规则(包括任何适配器),而不必测试不应该测试的原则类型对象,因为大多数情况下,这是第三方代码。

这样做还可以使您更容易在未来更改业务规则。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21470181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档