繁体   English   中英

单元测试持久层 - Symfony

[英]Unit test persistence layer - Symfony

我想在Symfony2中测试持久性。 我想知道它是否更好的模拟实体并提供给实体经理或者它是更好的模拟实体menager并将实体传递给经理?

我的第一个选项但是实体管理器抛出异常而不是对象不是实体主义。 如何在PHPUNIT中测试持久性symfony?

您应该编写持久层的集成测试 ,而不是编写单元测试

单元测试中有一条规则“ 不要嘲笑你不拥有的东西 ”。

您不拥有Doctrine类和接口,并且您永远无法确定您对所模拟的接口所做的假设是否正确。 即使你在编写测试时它们是正确的,你也无法确定Doctrine的行为是否随着时间而改变。

每当您使用第三方代码时,您应该为任何使用它编写集成测试。 集成测试实际上将调用数据库并确保该学说按照您认为的方式工作。

这就是为什么从第三方的东西中解脱出来的好处。

在学说的情况下,这很容易。 您可以做的一件事是为每个存储库引入一个接口。

interface ArticleRepository
{
    /**
     * @param int $id
     *
     * @return Article
     *
     * @throws ArticleNotFoundException
     */
    public function findById($id);
}

您可以轻松地模拟或存根这样的界面:

class MyServiceTest extends \PHPUnit_Framework_Test_Case
{
    public function test_it_does_something()
    {
        $article = new Article();
        $repository = $this->prophesize(ArticleRepository::class);
        $repository->findById(13)->willReturn($article);

        $myService = new MyService($repository->reveal());
        $myService->doSomething();

        // ...
    }
}

该接口将使用doctrine实现:

use Doctrine\ORM\EntityRepository;

class DoctrineArticleRepository extends EntityRepository implement ArticleRepository
{
    public function findById($id)
    {
        // call doctrine here
    }
}

实现就是你要编写的集成测试。 在您对存储库的集成测试中,您实际上将调用数据库:

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;

class ArticleTest extends KernelTestCase
{
    private $em;
    private $repository;

    protected function setUp()
    {
        self::bootKernel();

        $this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager();
        $this->repository = $this->em->getRepository(Article::class);
    }

    public function test_it_finds_an_article()
    {
         $this->createArticle(13);

         $article = $this->repository->findById(13);

         $this->assertInstanceOf(Article::class, $article);
         $this->assertSame(13, $article->getId());
    }

    /**
     * @expectedException ArticleNotFoundException
     */
    public function test_it_throws_an_exception_if_article_is_not_found()
    {
        $this->repository->findById(42);
    }

    protected function tearDown()
    {
        parent::tearDown();

        $this->em->close();
    }

    private function createArticle($id)
    {
        $article = new Article($id);
        $this->em->persist($article);
        $this->em->flush();
        // clear is important, otherwise you might get objects stored by doctrine in memory
        $this->em->clear();
    }
}

在其他任何地方,您将使用将被存根(或模拟)的接口。 在其他任何地方你都不会打到数据库。 这使您的测试更快。

存根中的实体可以简单地创建或存根。 大多数时候我创建实体对象而不是模拟它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM