我可以将 Mockery 中的 shouldReceive 和 shouldNotReceive 与 Doctrine Entity Manager 结合起来进行 ZF2 中的控制器测试吗?

Can I combine shouldReceive and shouldNotReceive in Mockery for a Controller Test in ZF2 with Doctrine Entity Manager?

我目前正在做一个 ZF2/Doctrine 项目,我正在尝试启动我的 PHPUnit 套件和 运行。第一次尝试为 ZF2 项目、一个 Doctrine 项目编写单元测试,也是第一次使用 Mockery。到目前为止一切顺利,但我遇到了 Doctrine 的问题 EntityManager;

我刚刚模拟了我的 Doctrine\Orm\EntityManager 并且我想要一个带有特定参数的 getRepository 调用 return 模拟存储库,但我希望对其他存储库的调用保持不变。我假设同时使用 shouldReceiveshouldNotReceive 会起作用,但不知何故我不断出错;

class ProductControllerTest extends AbstractHttpControllerTestCase
{
    public function testViewAction()
    {
        $serviceLocator = $this->getApplicationServiceLocator();
        $entityManager = \Mockery::mock($serviceLocator->get('Doctrine\ORM\EntityManager'));

        $entityManager
           ->shouldReceive('getRepository')
           ->with('App\Entity\Product')
           ->andReturn(\Mockery::mock('App\Repository\Product'));

        $entityManager
           ->shouldNotReceive('getRepository')
           ->with(\Mockery::not('App\Entity\Product'));

        $serviceLocator
            ->setAllowOverride(true)
            ->setService('Doctrine\ORM\EntityManager', $entityManager);

        $this->dispatch('/products/first-product');

        $this->assertResponseStatusCode(200);
    }
}

我之所以想要这个特别的东西是因为我只想为这段代码编写一个测试。一些底层代码并不完美,所以请帮助我专注于这部分,但我希望能够在不破坏我的应用程序的情况下重构底层代码。必须从某个地方开始让我的应用程序完全可测试 ;)

但是我的逻辑中有什么地方有缺陷或者我遗漏了什么吗?非常感谢!

你可以尝试这样的事情。这个想法是首先使用 byDefault() 设置默认期望,然后定义您的特定期望,这将优先于默认期望。

$entityManager
    ->shouldReceive('getRepository')
    ->with(\Mockery::any())
    ->andReturn(\Mockery::mock('Doctrine\ORM\EntityRepository'))
    ->byDefault();

$entityManager
    ->shouldReceive('getRepository')
    ->with('App\Entity\Product')
    ->andReturn(\Mockery::mock('App\Repository\Product'));