在尝试模拟Doctrine 2 Entity Repository时在PHPUnit中获取错误

bla*_*ong 1 php unit-testing doctrine doctrine-orm zend-framework2

我正在使用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
    );
}
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我使用以下方法来创建实体管理器和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);

}
Run Code Online (Sandbox Code Playgroud)

上面的代码基于我在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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

Jas*_*man 7

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

所以你可以使用模拟构建器

$repositoryMock =
    $this->getMockBuilder('\Doctrine\ORM\EntityRepository')->getMock();
Run Code Online (Sandbox Code Playgroud)

或者删除在findBy()别处调用的函数

$repositoryMock->expects($this->any())
    ->method('findBy')
    ->will($this->returnValue(null));
Run Code Online (Sandbox Code Playgroud)

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

编辑:

我只是注意到你在嘲笑你的实体,但你需要嘲笑你的存储库或Doctrine.请参阅我上面编辑的评论.如果保留该findBy()方法,则只需模拟EntityRepository类即可.如果你有自己的(例如Resources\Repository\FileTypeRepository),你可以改为模拟它.

此外,您可能需要将\MockBuilder调用的开头放在正确的命名空间中.