gpt4 book ai didi

unit-testing - 如何使用 Symfony 在 serviceTest 中模拟 EntityManager?

转载 作者:行者123 更新时间:2023-12-04 05:07:43 24 4
gpt4 key购买 nike

对不起,我的问题很长。

如何在扩展 KernelTestCase 的服务测试中模拟 entityManager?

现在,解释和我的测试......

我正在使用 Symfony3.2。我的应用程序是标准的。我有一些 Controller ,我使用 WebTestCase 来测试它们。

一般来说,我的 Controller 验证参数,调用服务/管理器,处理一些变量并将它们推送到查看,我的测试在测试扩展中非常简单 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 , 因为我用 服务 和这些线把我的服务模拟
    //We create the client
$client = static::createClient();
$container = $client->getContainer();

//I put my mock here
$container->set('app.game-service', $fooService);

我在我的服务中模拟实体管理器时遇到问题。我的 Controller 经过测试,但不是我的服务。

这是构造函数初始化一个简单的 protected 属性实体管理器。问题是 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 完美运行,有一些数据库交互。

我知道我可以在测试期间回滚数据。但我想模拟 entityManager 验证 的来电 commit 方法 .

我尝试在我的 setUp 中模拟实体管理器:
    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 属性更改为 公众

我这样做:
    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)属性(property)中拥有 entityManager 并不是一个好习惯

我的问题是:如何在服务测试中模拟 entityManager?

(对不起,我英语不太好)

最佳答案

首先在你的代码中

$container->set('doctrine.orm.entity_manager'); // THIS LINE DOES NOTHING <=======

我确定你错过了第二个参数:)

另注: 不要 mock 你不拥有的东西 .
将来您将运行 composer update和 EntityManager 的 commit会有一些可选的 isReallyCommit范围。你的代码会被破坏,但你不会注意到它,因为测试是绿色的。我知道这不太可能,但无论如何这只是示例。我认为这里的好习惯是
  • 有一些带有实体管理器的适配器
  • 在服务单元测试中模拟该适配器
  • 在不模拟任何东西的情况下,通过针对真实数据库的功能测试来测试您的适配器

  • 或者干脆不要 单位测试您的服务,但制作 功能 具有真实数据库交互的测试

    关于unit-testing - 如何使用 Symfony 在 serviceTest 中模拟 EntityManager?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40950330/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com