gpt4 book ai didi

php - 单元测试持久层 - Symfony

转载 作者:可可西里 更新时间:2023-10-31 23:52:55 24 4
gpt4 key购买 nike

我想在 Symfony2 中测试持久性。我想知道它是更好的模拟实体并提供给实体管理器还是更好的模拟实体管理器并将实体传递给管理器?

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

最佳答案

与其编写单元测试,不如为持久层编写集成测试

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

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

每当您使用第 3 方代码时,您都应该为使用它的任何内容编写集成测试。集成测试实际上会调用数据库并确保该原则按照您认为的方式工作。

这就是为什么最好从第 3 方的东西解耦

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

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

您可以轻松模拟或 stub 这样的接口(interface):

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();

// ...
}
}

该接口(interface)将与学说一起实现:

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();
}
}

在其他任何地方,您都将使用将被 stub (或模拟)的接口(interface)。在其他任何地方你都不会访问数据库。这使您的测试速度更快。

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

关于php - 单元测试持久层 - Symfony,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35030745/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com