如何使用 Symfony 在 serviceTest 中模拟 EntityManager?
How to Mock EntityManager in a serviceTest with Symfony?
抱歉,我的问题很长。
如何在扩展 KernelTestCase 的服务测试中模拟 entityManager?
现在,解释和我的测试...
我正在使用 Symfony3.2。我的应用程序是标准的。我有一些控制器,我使用 WebTestCase 来测试它们。
一般来说,我的控制器验证参数,调用 service/a 管理器,处理一些变量并将它们推送到视图,我的测试在测试扩展 WebTestCase 中非常简单。
/**
* Test New Game Action
*/
public function testFooAction(){
//We mock the Service
$fooService = $this
->getMockBuilder(GameService::class)
->disableOriginalConstructor()
->getMock();
$fooService->expects(self::once())
->method('barMethod')
->willReturn($result);
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
//I launch the request
$client->request('GET', '/foo');
//I handle the response
$response = $client->getResponse();
//I do some tests like this one
self::assertEquals(200, $response->getStatusCode());
}
如您所见,我没有调用 EntityManger,因为我使用 Services 和这些行来放置我的 Services 的 Mock
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
我在服务中模拟实体管理器时遇到问题。我的控制器经过测试但未经过我的服务。
这里是构造函数初始化了一个简单的protected 属性 entityManager。问题是这个 protected 正如您将进一步看到的...
/**
* FooService constructor.
* @param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
为了测试我的服务,这是我的初始代码:
<?php
class FooServiceTest extends KernelTestCase
{
/**
* Foo Service.
*
* @var FooService
*/
private $fooService;
/**
* Prepares the environment before running each test.
*/
protected function setUp()
{
parent::setUp();
self::bootKernel();
$this->fooService = static::$kernel->getContainer()
->get('app.foo-service') //HERE IS HOW I HANDLE MY SERVICE TO TEST IT
;
}
testStart 完美运行,有一些数据库交互。
我知道我可以在测试期间回滚数据。但是我想Mock entityManager 来验证 commit
method.
的调用
我尝试在我的设置中模拟实体管理器:
protected function setUp()
{
parent::setUp();
$entityManager = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManager
->expects(once()) // I WANT EXACTLY ONE CALL TO COMMIT METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$container = static::$kernel->getContainer();
$container->set('doctrine.orm.entity_manager', $entityManager); // THIS LINE DOES NOTHING <=======
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
这些代码不起作用。模拟不到位。我还有真正的 entityManager。我认为这是因为容器已经关闭。设置
是否有用
像野蛮人一样,我将 entityManager 属性 更改为 public
我这样做了:
protected function setUp()
{
parent::setUp();
$entityManagerMock = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManagerMock
->expects(once()) // I WANT EXACTLY ONE CALL TO commit METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
$this->gameService->entityManager = entityManagerMock;
效果很好。测试可以是运行。但是在 public 属性
中使用 entityManager 并不是一个好习惯
我的问题是:如何在服务测试中模拟 entityManager?
(对不起,我的英文不流利)
首先在你的代码中
$container->set('doctrine.orm.entity_manager'); // THIS LINE DOES NOTHING <=======
我确定你错过了第二个参数:)
另一个注意事项:不要嘲笑你不拥有的东西。
将来您将 运行 composer update
和 EntityManager 的 commit
将有一些可选的 isReallyCommit
参数。你的代码会被破坏,但你不会注意到它,因为测试是绿色的。我知道这不太可能,但无论如何这只是一个例子。我认为这里的好做法是
- 有一些封装了实体管理器的适配器
- 在服务单元测试中模拟该适配器
- 在不模拟任何东西的情况下,通过针对真实数据库的功能测试来测试您的适配器
或者只是不 unit 测试您的服务,而是使用真实的数据库交互进行 功能性 测试
抱歉,我的问题很长。
如何在扩展 KernelTestCase 的服务测试中模拟 entityManager?
现在,解释和我的测试...
我正在使用 Symfony3.2。我的应用程序是标准的。我有一些控制器,我使用 WebTestCase 来测试它们。
一般来说,我的控制器验证参数,调用 service/a 管理器,处理一些变量并将它们推送到视图,我的测试在测试扩展 WebTestCase 中非常简单。
/**
* Test New Game Action
*/
public function testFooAction(){
//We mock the Service
$fooService = $this
->getMockBuilder(GameService::class)
->disableOriginalConstructor()
->getMock();
$fooService->expects(self::once())
->method('barMethod')
->willReturn($result);
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
//I launch the request
$client->request('GET', '/foo');
//I handle the response
$response = $client->getResponse();
//I do some tests like this one
self::assertEquals(200, $response->getStatusCode());
}
如您所见,我没有调用 EntityManger,因为我使用 Services 和这些行来放置我的 Services 的 Mock
//We create the client
$client = static::createClient();
$container = $client->getContainer();
//I put my mock here
$container->set('app.game-service', $fooService);
我在服务中模拟实体管理器时遇到问题。我的控制器经过测试但未经过我的服务。
这里是构造函数初始化了一个简单的protected 属性 entityManager。问题是这个 protected 正如您将进一步看到的...
/**
* FooService constructor.
* @param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
为了测试我的服务,这是我的初始代码:
<?php
class FooServiceTest extends KernelTestCase
{
/**
* Foo Service.
*
* @var FooService
*/
private $fooService;
/**
* Prepares the environment before running each test.
*/
protected function setUp()
{
parent::setUp();
self::bootKernel();
$this->fooService = static::$kernel->getContainer()
->get('app.foo-service') //HERE IS HOW I HANDLE MY SERVICE TO TEST IT
;
}
testStart 完美运行,有一些数据库交互。
我知道我可以在测试期间回滚数据。但是我想Mock entityManager 来验证 commit
method.
我尝试在我的设置中模拟实体管理器:
protected function setUp()
{
parent::setUp();
$entityManager = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManager
->expects(once()) // I WANT EXACTLY ONE CALL TO COMMIT METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$container = static::$kernel->getContainer();
$container->set('doctrine.orm.entity_manager', $entityManager); // THIS LINE DOES NOTHING <=======
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
这些代码不起作用。模拟不到位。我还有真正的 entityManager。我认为这是因为容器已经关闭。设置
是否有用像野蛮人一样,我将 entityManager 属性 更改为 public
我这样做了:
protected function setUp()
{
parent::setUp();
$entityManagerMock = $this
->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock();
$entityManagerMock
->expects(once()) // I WANT EXACTLY ONE CALL TO commit METHOD
->method('commit')
->willReturn(null);
self::bootKernel();
$this->gameService = static::$kernel->getContainer()
->get('app.game-service')
;
$this->gameService->entityManager = entityManagerMock;
效果很好。测试可以是运行。但是在 public 属性
中使用 entityManager 并不是一个好习惯我的问题是:如何在服务测试中模拟 entityManager?
(对不起,我的英文不流利)
首先在你的代码中
$container->set('doctrine.orm.entity_manager'); // THIS LINE DOES NOTHING <=======
我确定你错过了第二个参数:)
另一个注意事项:不要嘲笑你不拥有的东西。
将来您将 运行 composer update
和 EntityManager 的 commit
将有一些可选的 isReallyCommit
参数。你的代码会被破坏,但你不会注意到它,因为测试是绿色的。我知道这不太可能,但无论如何这只是一个例子。我认为这里的好做法是
- 有一些封装了实体管理器的适配器
- 在服务单元测试中模拟该适配器
- 在不模拟任何东西的情况下,通过针对真实数据库的功能测试来测试您的适配器
或者只是不 unit 测试您的服务,而是使用真实的数据库交互进行 功能性 测试