交响乐 2.8 : inject mocked repository in a test controller

标签 symfony phpunit symfony-2.8

我尝试为自定义 Controller 创建测试。在此例中,执行的内容如下:

代码

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

在测试 Controller 中,这就是我正在做的事情:

$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

所以现在,我“只是”必须模拟存储库:

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

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

并将其注入(inject)到容器中:

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

但是我还是有同样的问题

最佳答案

不要在测试类中注入(inject)容器/实体管理器,而是注入(inject)学说存储库directly 。另外,不要在测试中创建内核,测试应该运行得很快。

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

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

关于交响乐 2.8 : inject mocked repository in a test controller,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43975569/

相关文章:

php - 如何获取Symfony2应用程序的根目录?

postgresql - 如何在学说查询中获取数组长度?

php - 应该如何使用 phpunit 测试 xss + sql 注入(inject)?

symfony - 如何在服务中获取当前登录的用户

apache - Apache 和 Nusphere PhpED 上的 PHPUnit 和 SimpleTest

php - Laravel web api 的测试策略

php - Symfony 添加 Bootstrap 表单控制类

php - Doctrine - 如何将数组绑定(bind)到 SQL?

symfony - 是否可以在 Twig 中创建一个对象?

symfony - 模型示例在 api 平台中未正确显示