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


基础教程推荐
- 如何替换eregi() 2022-01-01
- 如何在 Laravel 中使用 React Router? 2022-01-01
- YouTube API v3 点赞视频,但计数器不增加 2022-01-01
- 如何在 Laravel 5.3 注册中添加动态下拉列表列? 2021-01-01
- PHP PDO MySQL 查询 LIKE ->多个关键词 2021-01-01
- 学说 dbal querybuilder 作为准备好的语句 2022-01-01
- Cron Jobs 调用带有变量的 PHP 脚本 2022-01-01
- 在PHP中根据W3C规范Unicode 2022-01-01
- 有什么方法可以用编码 UTF-8 而不是 Unicode 返回 PHP`json_encode`? 2021-01-01
- PHP 类:全局变量作为类中的属性 2021-01-01