Symfony 2.8:在测试控制器中注入模拟存储库

Symfony 2.8 : inject mocked repository in a test controller

我尝试为自定义控制器创建一个测试。在这一个中,这是执行的内容:

代码

$users = $this->getDoctrine()
                ->getRepository('MyBundle:User')
                ->findAllOrderedByName();

在测试控制器中,这就是我正在做的:

$entityManager = $this
            ->getMockBuilder('Doctrine\ORM\EntityManager')
            ->setMethods(['getRepository', 'clear'])
            ->disableOriginalConstructor()
            ->getMock();

        $entityManager
            ->expects($this->once())
            ->method('getRepository')
            ->with('MyBundle:User')
            ->will($this->returnValue($userRepositoryMock));


        // Set the client
        $client = static::createClient();
        $client->getContainer()->set('doctrine.orm.default_entity_manager', $entityManager);

问题

但最后测试失败了,因为我的模拟似乎没有被使用:

tests\MyBundle\Controller\ListingControllerTest::testAllAction Expectation failed for method name is equal to string:getRepository when invoked 1 time(s). Method was expected to be called 1 times, actually called 0 times.

有什么想法吗?

编辑

根据评论的评论,我创建了一个服务:

services:
    my.user.repository:
        class:   MyBundle\Entity\UserRepository
        factory: ['@doctrine.orm.default_entity_manager', getRepository]
        arguments:
          - MyBundle\Entity\User

所以现在,我 "just" 必须模拟回购协议:

$userRepositoryMock = $this->getMockBuilder('MyBundle\Entity\UserRepository')
            ->disableOriginalConstructor()
            ->setMethods(['findAllOrderedByName'])
            ->getMock();

        $userRepositoryMock
            ->expects($this->once())
            ->method('findAllOrderedByName')
            ->will($this->returnValue($arrayOfUsers));

并将其注入容器:

$client->getContainer()->set('my.user.repository', $userRepositoryMock);

但我仍然遇到同样的问题

不要在测试中注入 container/entity 管理器 class,而是注入学说存储库 directly。另外,不要在测试中创建内核,测试应该 运行 快速。

更新 1: 测试服务应该在构造函数中需要存储库。所以在你的测试中你可以用 mock 替换它。 $client = static::createClient() 用于使用固定装置针对真实数据库测试控制器(功能测试)。不要使用它来测试具有模拟依赖项的服务(单元测试)。

更新 2:单元测试示例:

class UserServiceTest extends UnitTestCase
{
    public function test_that_findAllWrapper_calls_findAllOrderedByName()
    {

        //GIVEN
        $arrayOfUsers = [$user1, $user2];

        $userRepo = $this->getMockBuilder('AppBundle\Repository\UserRepository')
            ->disableOriginalConstructor()
            ->getMock();
        $userRepo
            ->expects($this->once())
            ->method('findAllOrderedByName')->willReturn($arrayOfUsers);


        $userService = new UserService($userRepo);

        //WHEN
        $result = $userService->findAllWrapper();

        //THEN
        $this->assertEquals($arrayOfUsers, $result);
    }
}

class UserService {
    private $userRepo;

    public function __construct(UserRepository $repo)
    {
        $this->userRepo = $repo;
    }

    public function findAllWrapper()
    {
        return $this->userRepo->findAllOrderedByName();
    }
}