在测试中更改数据库 table

ALTERing a database table inside a test

出于看似充分的理由,我需要更改 table 中的某些内容,该内容是在测试 运行 时从夹具创建的。

在我尝试过的许多事情中,这就是我现在所拥有的。在我进入 ALTER 查询之前,首先我想确保我可以访问临时 table 所在的数据库。

public function testFailingUpdateValidation()
{
    // i will run SQL against a connection, lets get it's exact name
    // from one of it's tables; first get the instance of that table
    // (the setup was blindly copied and edited from some docs)
    $config = TableRegistry::getTableLocator()->exists('External/Products')
        ? []
        : ['className' => 'External/Products'];
    $psTable = TableRegistry::getTableLocator()
        ->get('External/Products', $config);
    // get the connection name to work with from the table
    $connectionName = $psTable->getConnection()->configName();
    // get the connection instance to run the query
    $db = \Cake\Datasource\ConnectionManager::get($connectionName);
    // run the query
    $statement = $db->query('SHOW TABLES;');
    $statement->execute();
    debug($statement->fetchAll());
}

输出为空。

########## DEBUG ##########
[]
###########################

我希望它至少有一个 table 我从中获得连接名称的名称。建立工作连接后,我将 运行 对特定列进行 ALTER 查询。

我该怎么做?请帮忙

我想我会澄清我在做什么,如果需要的话

这是集成代码测试的一部分。所涉及的方法已经过单独测试。我正在测试的方法中的代码从一个数据库 table 中获取一堆值并将它们复制到另一个数据库,然后它会立即验证两个 table 中的值是否匹配。当他们不这样做时,我需要模拟一个案例。

我能想出的最好办法是更改 table 列的架构,以使其以低精度存储值,并导致我的代码测试在尝试匹配时失败(验证) 值。

问题是我没有为我想更改的 table 加载夹具。我知道这很明显,但我仍然感到困惑,因为为什么 SHOW TABLES return 其他 table 确实加载了它们的固定装置?它没有显示 tables 所以我认为它根本不起作用,甚至没有加载那个确切的夹具。一旦我这样做了,它现在会向我显示该灯具的 table,以及其他灯具。

无论如何,这是工作代码。希望它能帮助解决这个问题的人。

// get the table instance
$psTable = TableRegistry::getTableLocator()->get('External/Products');
// get the table's corresponding connection name
$connectionName = $psTable->getConnection()->configName();
// get the underlying connection instance by it's name
$connection = \Cake\Datasource\ConnectionManager::get($connectionName);
// get schemas available within connection
$schemaCollection = $connection->getSchemaCollection();
// describe the table schema before ALTERating it
$schemaDescription = $schemaCollection->describe($psTable->getTable());
// make sure the price column is initially DECIMAL
$this->assertEquals('decimal', $schemaDescription->getColumnType('price'));
// keep the initial column data for future reference
$originalColumn = $schemaDescription->getColumn('price');

// ALTER the price column to be TINYINT(2), as opposed to DECIMAL
$sql = sprintf(
    'ALTER TABLE %s '.
    'CHANGE COLUMN price price TINYINT(2) UNSIGNED NOT NULL', 
    $psTable->getTable()
);
$statement = $connection->query($sql);
$statement->closeCursor();
// describe the table schema after ALTERations
$schemaDescription = $schemaCollection->describe($psTable->getTable());
// make sure the price column is now TINYINT(2)
$this->assertEquals('tinyinteger', $schemaDescription->getColumnType('price'));

注意:完成此测试后,我必须使用上面 $originalColumn 中的数据将列恢复到其初始类型。