【问题标题】:Getting errors in PHPUnit when trying to mock Doctrine 2 Entity Repository尝试模拟 Doctrine 2 Entity Repository 时在 PHPUnit 中出现错误
【发布时间】:2015-02-12 11:26:46
【问题描述】:

我正在使用 Doctrine 2 构建一个 ZF2 应用程序,并尝试使用模拟对象对其进行测试。我尝试测试的原始操作如下:

public function indexAction()
{   
    $title = 'File Types';
    $this->layout()->title = $title;

    $em = $this->serviceLocator->get('entity_manager');

    $fileTypes = $em->getRepository('Resource\Entity\FileType')
        ->findBy(array(), array('type' => 'ASC'));

    return array(
        'title' => $title,
        'fileTypes' => $fileTypes
    );
}

在我的测试中,我使用以下方法来创建实体管理器和 FileTypes 实体存储库的模拟:

public function mockFiletypeResult($output)
{
    $emMock = $this->getMockBuilder('Doctrine\ORM\EntityManager')
        ->disableOriginalConstructor()
        ->getMock();

    $repositoryMock = $this->getMock('Resource\Entity\FileType');

    $repositoryMock->expects($this->any())
        ->method('findBy')
        ->will($this->returnValue($output));

    $emMock->expects($this->any())
        ->method('getRepository')
        ->will($this->returnValue($repositoryMock));

    $this->getApplicationServiceLocator()->setAllowOverride(true);
    $this->getApplicationServiceLocator()->setService('Resource\Entity\FileType', $repositoryMock);
    $this->getApplicationServiceLocator()->setService('Doctrine\ORM\EntityManager', $emMock);

}

上面的代码是基于我在this post on stackoverflow读到的。

问题是,当我运行测试时,我收到以下错误:Fatal error: Call to undefined method Mock_FileType_39345bde::findBy() in /path/to/test。我究竟做错了什么?我环顾了一堆,但似乎无法找出问题所在。

编辑:我最初写的错误消息是抱怨未识别的 findAll() 方法,而实际上它是 findBy()。

编辑 2:我已经尝试向我的实体存储库添加一个新方法,如下所示:

public function getFileTypes()
{
    $query = $this->_em->createQuery('SELECT t
        FROM Resource\Entity\FileType t
        ORDER BY t.type ASC, t.extension ASC');

    return $query->getResult();
}

然后我尝试在我的控制器中用 getFileTypes 替换 findBy 方法,并在模拟中删除 getFileTypes。同样的问题:它说找不到方法。

还有一件事:不确定是否重要,但我使用的是 PHPUnit 3.7 版。出于某种原因,我认为 4.x 版本不能与 ZF2 一起正常工作。我应该升级吗?

【问题讨论】:

    标签: php unit-testing doctrine-orm zend-framework2 doctrine


    【解决方案1】:

    如果您不在您的存储库上使用getMockBuilder(),它将希望您对任何被调用的方法进行存根。如果您使用getMockBuilder(),它将自动将所有函数替换为返回null 的虚拟实现。

    所以你可以使用模拟生成器

    $repositoryMock =
        $this->getMockBuilder('\Doctrine\ORM\EntityRepository')->getMock();
    

    或将在别处调用的 findBy() 函数存根

    $repositoryMock->expects($this->any())
        ->method('findBy')
        ->will($this->returnValue(null));
    

    查看更多:https://phpunit.de/manual/current/en/test-doubles.html

    编辑:

    我刚刚注意到您正在模拟您的实体,但您需要模拟您的存储库或 Doctrine 的。请参阅上面我编辑的评论。如果您保留 findBy() 方法,您可以简单地模拟 EntityRepository 类。如果您有自己的(例如 Resources\Repository\FileTypeRepository),则可以模拟它。

    此外,您可能需要将 \ 放在 MockBuilder 调用的开头,以便正确命名它们。

    【讨论】:

    • 我刚刚尝试了你的两个建议(当然假设你是想说$repositoryMock = $this->getMockBuilder('Resource\Entity\FileType')->getMock() :)。我仍然得到相同的结果。我还尝试向存储库添加一个新方法(请参阅我原始问题中的编辑),但仍然没有骰子。
    • 我最近确实遇到了一些麻烦,我不得不模拟 find() 方法,而不是在模拟的存储库上,而是在模拟的实体管理器上。但是,实体管理器上没有findAll()。当你尝试不同的方法时,它是否还在抱怨findAll()
    • 哦,快!我在我的问题中输入了错误的错误信息!原始消息是它找不到 findBy 方法。然后我尝试切换到 findAll,但得到了相同的结果——我不小心从控制台窗口复制了错误的代码!
    • 更新了我的帖子,我想我发现了这个问题 - 你需要模拟包含 findBy() 函数的实体存储库,而不是你的实体。
    • 当然!事后看来,这是一个如此明显的解决方案,但我只是没有看到它。谢谢!
    猜你喜欢
    • 2013-10-10
    • 1970-01-01
    • 2023-01-18
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 2022-12-29
    相关资源
    最近更新 更多