我有一个自定义实体存储库。例如,它看起来像这样:
namespace Foo\Repository;
use Doctrine\ORM\EntityRepository;
class Article extends EntityRepository
{
public function findRecent($limit)
{
$qb = $this->createQueryBuilder('a');
$qb->andWhere('a.publishDate IS NOT NULL')
->orderBy('a.publishDate', 'DESC')
->setMaxResults($limit);
return $qb->getQuery()->getResult();
}
}
我想在这种情况下进行测试:
- “最近”中有一个 ORDER BY
- 有一个限制
- 实体必须有发布日期
我不想验证查询生成器的 SQL 输出,因为 Doctrine 可以在不同版本之间更改 SQL。那会破坏我的单元测试。因此,我的想法是这样的:
- 创建我的存储库的模拟
- 创建查询构建器的模拟
- 确保
$this->createQueryBuilder('a')
返回模拟查询生成器 - 在查询生成器上测试方法调用
在代码中:
namespace FooTest\Repository;
use PHPUnit_Framework_TestCase as TestCase;
class ArticleRepositoryTest extends TestCase
{
protected $qb;
protected $repository;
public function setUp()
{
$this->qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder')
->disableOriginalConstructor()
->getMock();
$this->repository = $this->getMockBuilder('Foo\Repository\Article')
->disableOriginalConstructor()
->getMock();
$this->repository->expects($this->once())
->method('createQueryBuilder')
->with($this->equalTo('a'))
->will($this->returnValue($this->qb));
}
public function testFindRecentLimitsToGivenLimit()
{
$limit = '1';
$this->qb->expects($this->any())
->method('setMaxResults')
->with($this->equalTo($limit));
$this->repository->findRecent($limit);
}
public function testFindRecentOrdersByPublishDate()
{
$this->qb->expects($this->any())
->method('andWhere')
->with($this->equalTo('a.publishDate'), $this->equalTo('DESC'));
$this->repository->findRecent(1);
}
}
但是,此findRecent()
调用从不内部调用createQueryBuilder
。PhpUnit 指出:
FooTest\Repository\ArticleRepositoryTest::testFindRecentLimitsToGivenLimit 方法名称的期望失败等于调用 1 次。方法预期被调用 1 次,实际上被调用 0 次。
我认为我在创建存储库模拟时做错了。我怎样才能确保这种方法有效?或者如果有更好的选择,那是什么?