我有一个自定义实体存储库。例如,它看起来像这样:
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 次。
我认为我在创建存储库模拟时做错了。我怎样才能确保这种方法有效?或者如果有更好的选择,那是什么?