Question

I am trying to run a simple unit test on my model. The problem is every time I run the test, my database table is dropped. I have public $dropTables = false; Can anyone figure out why the merchant_rejects table is still being dropped? As you will see, I've tried many different methods in my fixture.

I guess I will have to step through the code and figure out when the table is dropped.

Here is the code for my fixture MovieStarFixture.php:

class MovieStarFixture extends CakeTestFixture {
//  NEW TRY from http://stackoverflow.com/a/2548908/55124
var $name = 'MovieStar';
var $fields = array(
    'id'       => array(
                      'type'=>'string',
                      'null' => false,
                      'default' => NULL,
                      'length' => 36,
                      'key' => 'primary'),

    'movie_id' => array(
                      'type'=>'string',
                      'null' => false,
                      'default' => NULL,
                      'length' => 36),

    'trace' => array('type'=>'string', 'null' => false, 'default' => NULL),
    'star_date' => array(
                       'type'=>'datetime',
                       'null' => false,
                       'default' => NULL),
    'movie_star_type_id' => array(
                       'type'=>'string',
                       'null' => false,
                       'default' => NULL,
                       'length' => 36),
    'code' => array('type'=>'text', 'null' => false, 'default' => NULL),
    'amount' => array('type'=>'float', 'null' => false, 'default' => 0),
    'movie_star_recurrance_id' => array(
                       'type'=>'string',
                       'null' => false,
                       'default' => NULL, 
                       'length' => 36),
    'open' => array('type'=>'boolean', 'null' => false, 'default' => '1'),
    'loss_axia' => array('type'=>'float', 'null' => true, 'default' => 0),
    'loss_mgr1' => array('type'=>'float', 'null' => true, 'default' => 0),
    'loss_mgr2' => array('type'=>'float', 'null' => true, 'default' => 0),
    'loss_rep' => array('type'=>'float', 'null' => true, 'default' => 0)
    );
var $records = array(
                array(
                'id' => '52ab9259-0070-4583-8d6f-4ac6c0a81cd7',
                'movie_id' => '440b7d13-5618-4560-be1d-93c5a2900a5e',
                'trace' => '3331313133423',
                'star_date' => '2013-12-13',
                'movie_star_type_id' => '64f7c386-6725-4c62-83ac-ae309bec8b10',
                 'code' => 'C01',
                'amount' => '222.0000',
                'movie_star_recurrance_id' => '',
                'open' => true,
                'loss_axia' => '23.0000',
                'loss_mgr1' => '0',
                'loss_mgr2' => '0',
                'loss_rep' => '0'
));

     //  THESE ARE ALL OF THE OTHER METHODS I HAVE TRIED
// Loading Fixture Methods / / / / / / / / / / / / / / / / / / / / / / / /  

// #1 - Import model and records / / / / / / / / / / / / / / / / / / / / /  
//public $import = array('model' => 'MovieStar', 'records' => true);


// #2 - Use onlt table info - no model / / / / / / / / / / / / / / / / / /  
// public $import = array('table' => 'movie_stars', 'records' => true);


// #3 - Specify Model and Create Records - Binds Data to Database/ / / / / 
/*
    public $records = array(
                 array(
        'MovieStar' => array(
        'id' => '52ab917d-549c-493b-9ef5-54a1c0a81cd7',
        'movie_id' => '440b7d13-5618-4560-be1d-93c5a2900a5e',
        'trace' => '3331313133',
        'star_date' => '2013-12-13',
        'movie_star_type_id' => '64f7c386-6725-4c62-83ac-ae309bec8b10',
        'code' => 'C01',
        'amount' => '122.0000',
        'movie_star_recurrance_id' => '',
        'open' => true,
        'loss_axia' => null,
        'loss_mgr1' => null,
        'loss_mgr2' => null,
        'loss_rep' => null
        )
    )
    );
public $import = array('model' => 'MovieStar', 'records' => false);
    */  

// #4 - Specify Model and Create Records in Init / / / / / / / / / / / / / 
// public $import = 'MovieStar';

/* public function init() {
        $records = array(
        array(
            'MovieStar' => array(
            'id' => '52ab917d-549c-493b-9ef5-54a1c0a81cd7',
            'movie_id' => '440b7d13-5618-4560-be1d-93c5a2900a5e',
            'trace' => '3331313133',
            'star_date' => '2013-12-13',
            'movie_star_type_id' => '64f7c386-6725-4c62-83ac-ae309bec8b10',
            'code' => 'C01',
            'amount' => '122.0000',
            'movie_star_recurrance_id' => '523525',
            'open' => true,
            'loss_axia' => null,
            'loss_mgr1' => null,
            'loss_mgr2' => null,
            'loss_rep' => null
              )
        )
        );
        parent::init();
}*/

// #5 - Try Model Setup / / / / / / / / / / / / / / / / / / / / / / / / 
// This drops all records after the first test
/*public $records = array(
     array(
        'MovieStar' => array(
        'id' => '52ab917d-549c-493b-9ef5-54a1c0a81cd7',
        'movie_id' => '440b7d13-5618-4560-be1d-93c5a2900a5e',
        'trace' => '3331313133',
        'star_date' => '2013-12-13',
        'movie_star_type_id' => '64f7c386-6725-4c62-83ac-ae309bec8b10',
        'code' => 'C01',
        'amount' => '122.0000',
        'movie_star_recurrance_id' => '',
        'open' => true,
        'loss_axia' => null,
        'loss_mgr1' => null,
        'loss_mgr2' => null,
        'loss_rep' => null
    )
       )
    );

   }*/

This is my MovieStarTest.php :

<?php
App::uses('Controller', 'Controller');
App::uses('View', 'View');
App::uses('MovieStar', 'Model');

/**
 * MovieStar Test Case
 *
 */
class MovieStarTest extends CakeTestCase {

/**
 * Fixtures
 *
 * @var array
 */
public $fixtures = array(
    'app.movie_star'//,
    //'app.movie_star_recurrance',
    //'app.movie_star_type',
    //'app.movie',
    //'app.user',
    //'app.movie_star_line',
    //'app.movie_star_status'
);

public $autoFixtures = false;
public $dropTables = false; 

/**
 * setUp method
 *
 * @return void
 */
public function setUp() {
    parent::setUp();

    $this->MovieStar =& ClassRegistry::init('MovieStar');
    $this->MovieStar->useDbConfig = 'test';

    //$this->MovieStar->query("SELECT truncate_tables('axia')");

    // load data
    $this->loadFixtures('MovieStar');
}

/**
 * tearDown method
 *
 * @return void
 */
public function testFixtures() {
    $numberOfResults = $this->MovieStar->find('count');
    debug($numberOfResults);
    $resultGreaterThanMinimumValue = $numberOfResults > 2;
    $this->assertTrue($resultGreaterThanMinimumValue);
}

public function testFixtures2() {
    $numberOfResults = $this->MovieStar->find('count');
    debug('$numberOfResults');
    debug($numberOfResults);
    $resultIsZero = $numberOfResults == 0;
    $this->assertTrue($resultIsZero);
}

public function testFindStarsByMovieId() {
    $movieId = '440b7d13-5618-4560-be1d-93c5a2900a5e';
    $result = $this->MovieStar->findStarsByMovieId($movieId);
    $expected = array(
        array(
'MovieStar' => array(
    'id' => '52ab9259-0070-4583-8d6f-4ac6c0a81cd7',
    'movie_id' => '440b7d13-5618-4560-be1d-93c5a2900a5e',
    'trace' => '3331313133423',
    'star_date' => '2013-12-13',
    'movie_star_type_id' => '64f7c386-6725-4c62-83ac-ae309bec8b10',
    'code' => 'C01',
    'amount' => '222.0000',
    'movie_star_recurrance_id' => '',
    'open' => true,
    'loss_axia' => '23.0000',
    'loss_mgr1' => null,
    'loss_mgr2' => null,
    'loss_rep' => null
        )
    )
    );

    debug("Expected");
    debug($expected);
    debug("Result");
    debug($result);

    $this->assertEquals($expected, $result);
}

public function tearDown() {
    //$this->MovieStar->deleteAll(true, true);
    //unset($this->MovieStar);

    parent::tearDown();
}

}

I am supposed to be able to not drop tables by adding

 public $dropTables = false; 

But I don't see the value of dropTables checked before this method in lib/Cake/TestSuite/Fixture/CakeFixtureManager.php enter image description here

Actually this would truncate the entire db. Where is my table being dropped?

Was it helpful?

Solution 2

It is default behaviour for CakePHP to create and drop all tables when testing.

So that they are (re)created for each test, you have the following options:

  1. Create the schema and the records in the Fixture.
  2. Import the schema from the database and create the records in the Fixture.
  3. Import the schema and the records from the database.

I use option no. 2 as I have too much data for CakePHP to import (and drop) for each test.

public $import = array('model' => 'YourModel', 'records' => false, 'connection' => 'default');

I specified the connection "default" so that CakePHP looks to my default connection to import schema information. I think the problem is that your $import variable is trying to import tables from the test connection. These will stop existing after the first run, when they are dropped.

OTHER TIPS

The accepted answer does not resolve the question:

I have public $dropTables = false; Can anyone figure out why the merchant_rejects table is still being dropped?

From cakephp docs:

$dropTables

Control table create/drops on each test method.

Set this to false to avoid tables to be dropped if they already exist between each test method. Tables will still be dropped at the end of each test runner execution.

Notice this part:

Tables will still be dropped at the end of each test runner execution

Therefore, even if you public $dropTables = false; the table tied to the fixture will still be dropped after each test run. The accepted answer does not prevent this.

To prevent this do the following...

Create your fixture like this:

class MovieStarFixture extends CakeTestFixture {

    public $import = 'MovieStar';

    //data will be loaded into this fixture by the test cases

    // do not truncate movie_stars table between tests
    public function truncate($db){

        return null;
    }

    // do not drop movie_stars table between tests
    public function drop($db){

        return null;
    }
}

This prevents the fixture from truncating and dropping after each test method. This is done by causing the fixture to "pretend" that it drops and truncates the table between tests. However this means that the fixture will think the table is dropped and try to re-create it at the beginning of each test method run which will cause an error (warning about creating existing table), so you must also...

Do this:

In MovieStarTest add public $dropTables = false;. This will prevent the fixture from attempting to drop a table if it already exists. As a result of not dropping a table at the beginning of a test, the fixture will not attempt to create the table. This is what we want because the table already exists.

Now you will have your data persisted between your CakeTestCase::test*() method calls.

It looks like lib/Cake/TestSuite/Fixture/CakeFixtureManager.php has a shutDown() function that drops the database. I would love to know where in the code it is supposed to check the $dropTables value before reaching this function.enter image description here

Building on Xavier's answer, you can ensure the table is only populated once by doing the following without needing to set dropTables = false at the test level:

class MovieStarFixture extends CakeTestFixture
{

  public $import = ['model' => 'MovieStar', 'connection' => 'default', 'records' => true];

  private $created_flag = false;

  public function create($db)
  {
    $success = null;
    if (!$this->created_flag) {
      $success = parent::create($db);
    }
    return $success;
  }

  public function truncate($db)
  {
    $success = null;
    if (!$this->created_flag) {
      $success = parent::truncate($db);
    }
    return $success;
  }

  public function insert($db)
  {
    $success = null;
    if (!$this->created_flag) {
      $success = parent::insert($db);
      $this->created_flag = true;
    }
    return $success;
  }

  public function drop($db)
  {
    $success = null;
    if (!$this->created_flag) {
      $success = parent::drop($db);
    }
  }
}

There is always the trade off between isolation and speed to consider, but if you have a large table that won't be changed throughout the life time of your test then this can have a huge performance boost.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top