Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CakePHP unit test not recognizing fixtures

Tags:

I'm on CakePHP v3.x with phpunit v5.1.3. and my unit test does not seem to be recognizing the existance of my fixtures. It appears that the tests are reading from the local (default) database connection.

Here's my TestCase class:

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!
    }

Here's my fixture file:

<?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',
        ],
        ...

When I debug() the returned value from $this->Screens->find('all')->order(['id'=>'ASC'])->first() I see the first REAL record in the DB. Not my fixture.

What am I missing?

UPDATE1: Here are the connections defined in my config file:

'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,
    ],
],

Update

The contents of App\Test\Fixture (Don't think there's anything interesting happening here... I think it's just extending the Cake fixture class)

<?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']);
            }
        }
    }
}
like image 366
emersonthis Avatar asked Sep 08 '16 21:09

emersonthis


1 Answers

Have you tried reducing the scope of the problem by:

  1. Removing the inheritance with App\Test\Fixture
  2. Defining the Fixture schema by declaring the $fields property.
  3. Enabling query logging

Both of these would be temporary measure to try and make the problem simpler to solve. You might also want to use the --debug flag when running PHPUnit. This will make CakePHP output all the SQL used to create fixtures.

like image 199
Mark Story Avatar answered Sep 19 '22 09:09

Mark Story