CakePHP单元测试只工作一次,然后我必须重置数据库


CakePHP unit tests only work once, then I have to reset database

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

首先,我要为我们的users表构建测试。我有下面的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
          ]
      ];
}

我也有一个TestCase表:

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();
    }
    // ...
}

我第一次运行这个测试时,它工作得很好。如果我尝试再次运行它,那么我得到以下错误:

PHPUnit 4.8.27 by Sebastian Bergmann and contributor .

错误提示:SQLSTATE[42000]:语法错误或访问冲突:1101 BLOB/TEXT列"status"不能有默认值"in ?[/path-to-app/供应商/cakephp/cakephp/src/TestSuite/夹具/TestFixture.php,第232行)

异常:无法插入固定装置"App'Test'TestCase'Model'Table'UsersTableTest"测试用例。SQLSTATE[42S02]: Base table or view not found: 1146"carebook_test。用户不存在[/path-to-app/供应商/cakephp/cakephp/src/TestSuite/夹具/FixtureManager.php,第253行)

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

我做错了什么?

编辑:这样做的原因似乎是一旦测试结束,表就被删除了。但是如果表不存在,测试不会自动创建表,所以测试只运行一次。我想知道是否有一种方法可以使表被截断而不是被删除。或者让fixture在表不存在的情况下创建它。我对这意味着如何工作有点困惑,因为我希望这个问题影响到每个人。

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

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

此行为不适合我,因为我的数据库表包含枚举列。CakePHP不支持ENUM列,而是将它们视为文本列。这意味着当表被重新创建时,它们有TEXT列而不是ENUM列。

这本来是可以的,只是我的ENUM列有一个默认值,而在Windows MySQL上试图在TEXT列上设置默认值会导致错误。这导致CakePHP的测试运行器出错,导致测试无法运行。

一个同事和我一起为CakePHP创建了一个插件,允许它与ENUM列正常工作。这个插件目前还没有公开发布,但我们计划在工作不那么忙的时候将其作为开源发布。

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

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

  • 如何使用插件
  • 如何配置附加类型

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

丢失表错误是由于DBO驱动程序堆栈中的"新"缓存特性引起的。DBO记住启动时存在的表,默认情况下不识别动态创建的表。

你可以禁用表的缓存:

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