Unit test persistence layer - Symfony(单元测试持久层 - Symfony)
问题描述
I want to test persistence in Symfony2. I wonder whether it is better mock entities and provide to entity manager or whether it is better mock entity menager and pass entity to manager ?
I first option but entity manager throw exception than object is not entity doctrine. How test persistence symfony in PHPUNIT?
Rather than writing unit tests you should write integration tests for the persistence layer.
There's a rule in unit testing "Don't mock what you don't own".
You don't own Doctrine classes nor interfaces, and you can never be sure that assumptions you made to the interfaces you mocked are true. Even if they're true at the time you write the test, you cannot be sure that Doctrine's behaviour didn't change over time.
Whenever you use 3rd party code you should write an integration test for whatever uses it. Integration test will actually call the database and make sure that doctrine works the way you think it works.
That's why it's good to decouple from 3rd party stuff.
In case of doctrine it's very easy. One of the things you could do is to introduce an interface for each of your repositories.
interface ArticleRepository
{
/**
* @param int $id
*
* @return Article
*
* @throws ArticleNotFoundException
*/
public function findById($id);
}
You can easily mock or stub such an 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();
// ...
}
}
The interface will be implemented with doctrine:
use DoctrineORMEntityRepository;
class DoctrineArticleRepository extends EntityRepository implement ArticleRepository
{
public function findById($id)
{
// call doctrine here
}
}
The implementation is what you're gonna write integration tests for. In your integration test for the repository you'll actually call the database:
use SymfonyBundleFrameworkBundleTestKernelTestCase;
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();
}
}
Everywhere else, you'll use the interface which will be stubbed (or mocked). Everywhere else you won't hit the database. This makes your tests fast.
Entities in your stubs can be simply created or stubbed. Most of the time I create entity objects rather then mock them.
这篇关于单元测试持久层 - Symfony的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:单元测试持久层 - Symfony
基础教程推荐
- Libpuzzle 索引数百万张图片? 2022-01-01
- 在 PHP 中强制下载文件 - 在 Joomla 框架内 2022-01-01
- 在多维数组中查找最大值 2021-01-01
- 在 Woocommerce 中根据运输方式和付款方式添加费用 2021-01-01
- 超薄框架REST服务两次获得输出 2022-01-01
- mysqli_insert_id 是否有可能在高流量应用程序中返回 2021-01-01
- WooCommerce 中选定产品类别的自定义产品价格后缀 2021-01-01
- 通过 PHP SoapClient 请求发送原始 XML 2021-01-01
- 如何在 PHP 中的请求之间持久化对象 2022-01-01
- XAMPP 服务器不加载 CSS 文件 2022-01-01