【问题标题】:CakePHP unit test not recognizing fixturesCakePHP 单元测试无法识别固定装置
【发布时间】:2016-09-08 21:34:02
【问题描述】:

我正在使用带有 phpunit v5.1.3 的 CakePHP v3.x。而且我的单元测试似乎没有认识到我的装置的存在。似乎测试正在从本地 (default) 数据库连接中读取。

这是我的 TestCase 类:

namespace App\Test\TestCase\Model\Table;

use Cake\Datasource\ConnectionManager;
use Cake\I18n\Time;
use Cake\ORM\TableRegistry;
use Cake\TestSuite\TestCase;

/**
 * App\Model\Table\ScreensTable Test Case
 *
 * @property \App\Model\Table\ScreensTable ScreensTable
 */
class ScreensTableTest extends TestCase
{
    /**
     * Fixtures
     *
     * @var array
     */
    public $fixtures = [
        'app.screens'
    ];

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

    public testSomethingHere(){
         $newScreen = $this->Screens->newEntity(['who' => 'cares']);
         $screen = $this->Screens->save($newScreen);
         // ^ This record will show up in my app's DB!
    }

这是我的夹具文件:

<?php
namespace App\Test\Fixture;

use App\TestSuite\Fixture\TestFixture;

/**
 * ScreensFixture
 *
 */
class ScreensFixture extends TestFixture
{
    /**
     * Records
     *
     * @var array
     */
    public $records = [
        [
            'id' => 2,
            'name' => 'Bla bla',
        ],
        ...

当我debug()$this-&gt;Screens-&gt;find('all')-&gt;order(['id'=&gt;'ASC'])-&gt;first() 的返回值时,我看到了数据库中的第一条 REAL 记录。不是我的固定装置。

我错过了什么?

更新1: 以下是我的配置文件中定义的连接:

'Datasources' => [
    'default' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Postgres',
        'persistent' => false,
        'host' => 'localhost',
        'port' => '5432',
        'username' => 'postgres',
        'password' => 'postgres',
        'database' => 'transitscreen',
        'encoding' => 'utf8',
        'timezone' => 'UTC',
        'cacheMetadata' => true,
        'quoteIdentifiers' => false,
    ],
    /**
     * Used by test suites
     */
    'test' => [
        'className' => 'Cake\Database\Connection',
        'driver' => 'Cake\Database\Driver\Postgres',
        'persistent' => false,
        'host' => 'localhost',
        'port' => '5432',
        'username' => 'postgres',
        'password' => 'postgres',
        'database' => 'ts_test',
        'encoding' => 'utf8',
        'timezone' => 'UTC',
        'cacheMetadata' => true,
        'quoteIdentifiers' => false,
    ],
],

更新

App\Test\Fixture 的内容(不要认为这里发生了什么有趣的事情……我认为它只是扩展了 Cake 夹具类)

<?php

namespace App\TestSuite\Fixture;

use Cake\I18n\Time;
use Cake\TestSuite\Fixture\TestFixture as CoreTestFixture;

/**
 * Override core TestFixture.
 */
class TestFixture extends CoreTestFixture
{

    /**
     * Initialize the fixture.
     *
     * @return void
     * @throws \Cake\ORM\Exception\MissingTableClassException When importing from a table that does not exist.
     */
    public function init()
    {
        $this->setRecordTimestamps();
        $this->encodeJsonColumns();

        parent::init();
    }

    /**
     * Set record timestamps.
     *
     * - created
     * - modified
     *
     * @return void
     */
    public function setRecordTimestamps()
    {
        foreach (['created', 'modified'] as $timestampField) {
            if (array_key_exists($timestampField, $this->fields)) {
                foreach ($this->records as &$record) {
                    $record[$timestampField] = new Time();
                }
            }
        }
    }

    /**
     * Encode JSON columns.
     *
     * Bake will output JSON fields as arrays (because of the `JsonType` object mapped to this field) but since
     * migrations execute directly against the database we need to encode these fields manually before insertion.
     *
     * @return void
     */
    public function encodeJsonColumns()
    {
        $fixtureName = namespaceSplit(get_called_class())[1];
        if ($fixtureName === 'DatasourcesFixture' && array_key_exists('widget_options', $this->fields)) {
            foreach ($this->records as &$record) {
                $record['widget_options'] = json_encode($record['widget_options']);
            }
        }
    }
}

【问题讨论】:

  • @AD7six 我在上面添加了我的数据库配置。它看起来对我来说是正确的,因为我定义了 defaulttest,并且在运行测试时我没有收到任何数据库连接错误。
  • 您是否已将夹具监听器添加到您的 phpunit.xml 中?
  • @code-kobold oooo 我不确定!请提交并回答我应该检查的内容。
  • @emersonthis sql 日志更有用/相关,因为它将证明是否使用了错误的数据库,“替代”的关键点是提供足够的信息 重现问题App\TestSuite\Fixture\TestFixture 现在你已经提供了它的源代码不允许这样做。
  • @AD7six 你能详细说明一下吗?为什么不允许?

标签: unit-testing cakephp phpunit cakephp-3.0


【解决方案1】:

您是否尝试通过以下方式缩小问题的范围:

  1. 使用 App\Test\Fixture 删除继承
  2. 通过声明 $fields 属性来定义 Fixture 架构。
  3. 启用query logging

这两个都是临时措施,可以让问题更容易解决。在运行 PHPUnit 时,您可能还想使用 --debug 标志。这将使 CakePHP 输出所有用于创建夹具的 SQL。

【讨论】:

    猜你喜欢
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多