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();
}
}
我尝试为自定义控制器创建一个测试。在这一个中,这是执行的内容:
代码
$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();
}
}