我有一个使用EntityManagerInterface的服务:
class DocFinderService
{
protected $em;
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
public function findDocs($specialtyCodes, $city, $state, $zip)
{...}
如何使用PHPUnit测试服务,具体来说,如何从测试函数传递 EntityManagerInterface 参数?
答案 0 :(得分:1)
当你编写单元测试时,我的意思是真正的UNIT测试(你也可以使用PHPUnit进行功能测试),你必须总是问自己想要测试什么。
您想测试EntityManager
吗?答案是不。更重要的是 - 即使EntityManager
由于一些奇妙的原因而停止正常工作,您的测试也应该通过。
所以你必须使用EntityManager
的模拟。请查看文档以获取更多详细信息https://phpunit.readthedocs.io/en/latest/test-doubles.html#mock-objects
mock的内容取决于findDocs
方法的代码。只要它是 find 函数,我认为你必须测试findDocs
返回一些数据,如果ORM层能够找到一些并返回null(或空数组或抛出异常),如果没有数据由ORM层找到。
class DocFinderService extends TestCase {
public function testFound() {
/** @var EntityManagerInterface | MockObject $entityManager */
$entityManager = $this->createMock(EntityManagerInterface::class);
/** @var ObjectRepository | MockObject $repo */
$repo = $this->createMock(ObjectRepository::class);
$repo->expects($this->once())->method('findBy')->willReturn([new DocEntity('doc_id_1'), new DocEntity('doc_id_2')]);
$entityManager->expects($this->once())->method('getRepository')->willReturn($repo);
$docFinder = new DocFinderService($entityManager);
$result = $docFinder->findDocs('SOME_SPECILAITY_CODE', 'City', 'State', 'ZIP');
$this->assertTrue(is_array($result));
$this->assertCount(2, $result);
}
public function testNotFound() {
/** @var EntityManagerInterface | MockObject $entityManager */
$entityManager = $this->createMock(EntityManagerInterface::class);
/** @var ObjectRepository | MockObject $repo */
$repo = $this->createMock(ObjectRepository::class);
$repo->expects($this->once())->method('findBy')->willReturn(null);
$entityManager->expects($this->once())->method('getRepository')->willReturn($repo);
$docFinder = new DocFinderService($entityManager);
$result = $docFinder->findDocs('SOME_SPECILAITY_CODE', 'City', 'State', 'ZIP');
$this->assertNull(result);
}
}
我还添加了ObjectRepository
的模拟,它假设在你的代码中你将用它来获取enity。您可以使用QueryBuilder
或其他方式用于相同目的。
这完全是关于" true"单元测试。如果您想在某些测试环境中使用真实的EntityManager
,那么您需要使用测试环境参数初始化您的应用程序或应用程序的某些部分,这些部分会对ORM层产生影响。但这是另一个长篇故事
答案 1 :(得分:0)
你可以像对待任何其他东西一样嘲笑它,并像对待另一个对象一样对它进行任何调用。
例如,这里是我使用名为Mockery(别名为'm ::')的库的片段,并告诉它我应该调用flush()
。
$em = m::mock(EntityManagerInterface::class);
$em->shouldReceive('flush');
$this->whc = new WebhookController($this->log, $this->eventDispatcher, $em);
你的模拟/存根需要多复杂取决于你的代码,以及它是多么可测试。