【问题标题】:CakePHP unit tests only work once, then I have to reset databaseCakePHP 单元测试只工作一次,然后我必须重置数据库
【发布时间】:2017-01-24 04:13:43
【问题描述】:

我正试图让我的团队开始为我们的应用程序进行一些单元测试。该应用程序是基于 CakePHP 构建的。

首先,我正在为我们的用户表构建测试。我有以下 Fixture 来创建一个供我测试的用户:

namespace App\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

class UsersFixture extends TestFixture
{
      public $connection = 'test';

      public $import = ['table' => 'users'];

      public $records = [
          [
              'username' => 'TestPass',
              'password' => '',
              'email' => 'TestPass@example.com',
              'status' => 'active',
              'created' => '2015-11-04 12:00:00',
              'last_logindate' => null,
              'registration_country' => 'AU',
              'system_user' => 0
          ]
      ];
}

我还有一个表格的测试用例:

namespace App\Test\TestCase\Model\Table;

use App\Model\Table\UsersTable;
use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;

/**
 * App\Model\Table\UsersTable Test Case
 */
class UsersTableTest extends TestCase
{

    /**
     * Fixtures
     *
     * @var array
     */
    public $fixtures = [
        'app.Users'
    ];

    /**
     * setUp method
     *
     * @return void
     */
    public function setUp()
    {
        parent::setUp();
        $config = TableRegistry::exists('Users') ? [] : ['className' => 'App\Model\Table\UsersTable'];
        $this->Users = TableRegistry::get('Users', $config);
    }

    /**
     * tearDown method
     *
     * @return void
     */
    public function tearDown()
    {
        unset($this->Users);

        parent::tearDown();
    }
    // ...
}

我第一次运行这个测试时它运行良好。如果我尝试再次运行它,则会收到以下错误:

Sebastian Bergmann 及其贡献者的 PHPUnit 4.8.27。

警告错误:“用户”的夹具创建失败“SQLSTATE [42000]: 语法错误或访问冲突:1101 BLOB/TEXT 列“状态”不能 有一个默认值”在 [/path-to-app/vendor/cakephp/cakephp/src/TestSuite/Fixture/TestFixture.php, 第232行]

例外:无法插入固定装置 “App\Test\TestCase\Model\Table\UsersTableTest”测试用例。 SQLSTATE [42S02]:未找到基表或视图:1146 表 'carebook_test.users' 中不存在 [/path-to-app/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php, 第253行]

我摆脱这个错误的唯一方法似乎是删除我的数据库,重新创建它,然后再次运行我的迁移。之后,测试将再次成功运行,然后再次中断。

我做错了什么?

编辑:似乎这样做的原因是,一旦测试结束,表就会被删除。但是如果表不存在,测试不会自动创建,所以测试只运行一次。我想知道是否有办法使表格被截断而不是被丢弃。或者,如果它不存在,Fixtures 将创建它。对它现在的工作方式有些困惑,因为我预计这个问题会影响到每个人。

EDIT2:我发现如果表不存在,CakePHP 确实是用来创建表的。对我来说,问题是我的列是一个 ENUM,而 CakePHP Fixtures 不支持枚举列,所以它使它成为一个文本列。枚举列可以有默认值(我的有),但文本列不能。所以我想我必须弄清楚如何让 CakePHP 接受枚举列。

【问题讨论】:

    标签: php mysql unit-testing cakephp phpunit


    【解决方案1】:

    问题在于 CakePHP 的 PHPUnit 类扩展添加了在运行测试后删除测试表的功能。在测试套件的下一次运行中,Fixtures 用于重新创建表。

    这种行为对我不起作用,因为我的数据库表包含 Enum 列。 CakePHP 不支持 ENUM 列,而是将它们视为文本列。这意味着当重新创建表时,它们具有 TEXT 列而不是 ENUM 列。

    这本来没问题,除了我的 ENUM 列有一个默认值,并且在 Windows 上 MySQL 试图在 TEXT 列上设置一个默认值会导致错误。这使 CakePHP 的测试运行器绊倒,并阻止了我的测试运行。

    我和一个同事一起为 CakePHP 创建了一个插件,它允许它与 ENUM 列一起正常工作。此插件目前尚未公开发布,但我们计划在工作不忙时将其作为开源版本发布。

    【讨论】:

      【解决方案2】:

      所以我想我必须弄清楚如何让 CakePHP 接受枚举列。

      是的。 CakePHP3 默认不支持枚举,因为它们不能在所有支持的数据库系统上工作。使用Enum Plugin 获取枚举支持。

      【讨论】:

      • 据我所知,该插件似乎并未添加对枚举的数据库支持,而是添加了一个枚举类,该类仍以整数形式存储在数据库中。对吗?
      【解决方案3】:

      我想你会发现枚举问题可以被忽略,只要枚举字段在你的测试中不起任何作用。

      缺少表错误是由于 DBO 驱动程序堆栈中的“新”缓存功能造成的。 DBO 会记住启动时存在的表,默认情况下不识别动态创建的表。

      您可以禁用表的缓存:

          public function setUp()
          {
              parent::setUp();
              $this->Users = ClassRegistry::init('Users');
              $this->Users->setDataSource('test2');
              $this->Users->cacheSources = false;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-08
        • 2018-06-18
        • 1970-01-01
        • 1970-01-01
        • 2019-01-01
        相关资源
        最近更新 更多