使用Codeception验收测试连接到多个数据库



我正试图找出如何使用Codeception连接到多个数据库。我甚至尝试直接实例化一个新的PDO实例,但随后codept run命令过早结束,没有错误消息。

我可以使用Db模块连接到一个数据库,使用$I->seeInDatabase()等功能,但我试图连接到两个。试图在运行时用$this->getModule('Db')->_reconfigure()重新配置Db模块也只是停止没有消息的测试。

任何想法?

我可以这样做:

套件配置文件:

actor: API_Tester
lint: true
colors: true
modules:
    enabled:
        - HelperApi
        - Asserts
        - REST:
            url: http://localhost
            depends: PhpBrowser
            part: Json
            headers:
              Accept: application/json
              Content-Type: application/json
        - Db:
            dsn: 'mysql:host=localhost;dbname=DATABASE1'
            user: 'DBUSER'
            password: 'DBPASSWORD'
            dump: 'tests/populate-DATABASE1.sql'
            populate: true
            cleanup: false
            reconnect: true
            populator: 'mysql -u $user -p$password -h $host $dbname < $dump'
            databases:
              DATABASE2_USE_THIS_NAME_IN_YOUR_CODE:
                dsn: 'mysql:host=localhost;dbname=DATABASE2'
                user: 'DBUSER'
                password: 'DBPASSWORD'
                dump: 'tests/populate-DATABASE2.sql'
                populate: true
                cleanup: false
                reconnect: true
                populator: 'mysql -u $user -p$password -h $host $dbname < $dump'
PHP测试代码:
        //Connect to the second database
        $I -> amConnectedToDatabase ( 'DATABASE2_USE_THIS_NAME_IN_YOUR_CODE' );
        $I -> seeNumRecords ( 1, 'users' );
        $I -> seeInDatabase ( 'users', [ 'email' => 'john@example.com' ] );
        //Connect back to the default database
        $I -> amConnectedToDatabase ( CodeceptionModuleDb::DEFAULT_DATABASE );
        $I -> seeNumRecords ( 1, 'sessions' );
        $I -> seeInDatabase ( 'sessions', [ 'uniqueness' => $this -> uuid ] );
结果:

I am connected to database "DATABASE2_USE_THIS_NAME_IN_YOUR_CODE"
I see num records 1,"users"
I see in database "users",{"email":"john@example.com"}
I am connected to database "default"
I see num records 1,"sessions"
I see in database "sessions",{"uniqueness":"635c798c-05cd-4d9d-b79a-9643...}

我认为这是你想要的:https://github.com/Codeception/Codeception/issues/1634…然而,它还没有实现-也许你可以推动这个问题?

好吧!如果你不使用模拟数据库连接,你可以做这件事,我在symfony中使用codeception时实现过一次。

  1. 使用

    抓取原则服务
    $doctrine = $I->grabService('Doctrine').
    
  2. 现在抓取数据库连接,正如你在doctrine ORM部分提到的。

    $connection = $doctrine->getConnection('DB_Name_as_in_ORM')
    
  3. 您现在已经连接到所需的数据库,现在您可以使用"doctrine dbal连接方法"对该数据库中的表执行查询。

我想这就是你要找的,也许!

我希望能够使用Doctrine多个管理器设置和所有codeception方法,但它一直在破坏(没有看到设置属性,只在默认管理器等上工作),这就是我想到的:在Helper中,我创建了使用Symfony模块设置条令管理器服务的方法:

class Shared extends CodeceptionModule
{
    public DoctrineORMEntityManagerInterface $em;
    /**
     * @param string $emAlias Name of your entity manager in doctrine.yaml
     */
    public function changeEm(string $emAlias): void
    {
        if ('internal' !== $connection && 'api' !== $emAlias) {
            throw new Error('Unknown connection: ' . $emAlias);
        }
        $doctrine = $this->getService(ManagerRegistry::class);
        $em = $doctrine->getManager($emAlias);
        // We need to verify that connection is open as it gets shut down on error
        if (!$em->isOpen()) {
            $doctrine->resetManager($emAlias);
        }
        $this->setEm($em, $emAlias);
    }
    public function setEm(EntityManagerInterface $em, string $emAlias): void
    {
        $this->em = $em; // Just to be safe and have access to selected entity        
        $this->getModule('Doctrine2')->em = $em;
        $sfModule = $this->getModule('Symfony');
        /** @var SymfonyBundleFrameworkBundleTestTestContainer $container */
        $container = $sfModule->_getContainer();
        $service = 'doctrine.orm.' . $emAlias . '_entity_manager';
        if ($container->initialized($service)) {
            return;
        }
        $container->set($service, $em);
        $sfModule->persistService($service, true);
    }
}

,并且总是在所有测试共享的方法的顶部设置默认实体管理器(在我的例子中,是测试父类中的_before):

abstract class BaseCestAbstract
{
    public function _before(ApiTester $I): void
    {
        $I->changeEm('internal'/'api');
        [...]
    } 
}

现在如果你想更改manager Codeception是使用mid-test:

    public function testA(ApiTester $I): void
    {
        $I->changeEm('internal');
        [...]
        $I->changeEm('api');
        [...]
    } 

所有的方法,如grabEntityFromRepository应该工作和辅助启动内核API调用应该使用相同的实体。

缺点:

我不知道如何使它与cleanup: true一起工作,这是一个痛苦,但我主要将其用于REST调用,这些调用无论如何都不能真正与清理一起工作,所以在我的情况下它是可以接受的。

版本:

  • Symfony: 6.2.6
  • Codeception: 5.0.8
  • codeception/module-doctrine2: 3.0.1
  • 教义/doctrine-bundle: 2.8.3

最新更新