3

我有一个自定义实体存储库。例如,它看起来像这样:

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();
    }
}

我想在这种情况下进行测试:

  1. “最近”中有一个 ORDER BY
  2. 有一个限制
  3. 实体必须有发布日期

不想验证查询生成器的 SQL 输出,因为 Doctrine 可以在不同版本之间更改 SQL。那会破坏我的单元测试。因此,我的想法是这样的:

  1. 创建我的存储库的模拟
  2. 创建查询构建器的模拟
  3. 确保$this->createQueryBuilder('a')返回模拟查询生成器
  4. 在查询生成器上测试方法调用

在代码中:

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 次。

我认为我在创建存储库模拟时做错了。我怎样才能确保这种方法有效?或者如果有更好的选择,那是什么?

4

2 回答 2

0

It looks to me like you are mocking the Repository you are trying to test, so findRecent() is indeed mocked and will return null.

You should be able to use the real repository instance.

于 2013-03-06T22:22:26.503 回答
0

setMethodsExcept()我发现测试子类存储库的解决方案是在构建模拟时添加一个调用。

因此,您可以setUp()像这样修改上面的代码:

$this->repository = $this->getMockBuilder('Foo\Repository\Article')
    ->disableOriginalConstructor()
    ->setMethodsExcept([
        // Insert any overridden/implemented functions here, in your case:
        'findRecent',
    ])
    ->getMock();
于 2017-11-09T15:28:13.160 回答