You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

356 lines
8.3 KiB

<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2019 British Columbia Institute of Technology
* Copyright (c) 2019 CodeIgniter Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2019 CodeIgniter Foundation
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
namespace CodeIgniter\Test;
use CodeIgniter\Config\Config;
use Config\Autoload;
use Config\Database;
use Config\Migrations;
use Config\Services;
use CodeIgniter\Database\BaseConnection;
use CodeIgniter\Database\MigrationRunner;
use CodeIgniter\Exceptions\ConfigException;
/**
* CIDatabaseTestCase
*/
class CIDatabaseTestCase extends CIUnitTestCase
{
/**
* Should the db be refreshed before
* each test?
*
* @var boolean
*/
protected $refresh = true;
/**
* The name of the fixture used for all tests
* within this test case.
*
* @var string
*/
protected $seed = '';
/**
* The path to where we can find the seeds directory.
* Allows overriding the default application directories.
*
* @var string
*/
protected $basePath = TESTPATH . '_support/Database';
/**
* The namespace to help us find the migration classes.
*
* @var string
*/
protected $namespace = 'Tests\Support\DatabaseTestMigrations';
/**
* The name of the database group to connect to.
* If not present, will use the defaultGroup.
*
* @var string
*/
protected $DBGroup = 'tests';
/**
* Our database connection.
*
* @var BaseConnection
*/
protected $db;
/**
* Migration Runner instance.
*
* @var MigrationRunner|mixed
*/
protected $migrations;
/**
* Seeder instance
*
* @var \CodeIgniter\Database\Seeder
*/
protected $seeder;
/**
* Stores information needed to remove any
* rows inserted via $this->hasInDatabase();
*
* @var array
*/
protected $insertCache = [];
//--------------------------------------------------------------------
/**
* Load any database test dependencies.
*/
public function loadDependencies()
{
if ($this->db === null)
{
$this->db = Database::connect($this->DBGroup);
$this->db->initialize();
}
if ($this->migrations === null)
{
// Ensure that we can run migrations
$config = new Migrations();
$config->enabled = true;
$this->migrations = Services::migrations($config, $this->db);
$this->migrations->setSilent(false);
}
if ($this->seeder === null)
{
$this->seeder = Database::seeder($this->DBGroup);
$this->seeder->setSilent(true);
}
}
//--------------------------------------------------------------------
/**
* Ensures that the database is cleaned up to a known state
* before each test runs.
*
* @throws ConfigException
*/
protected function setUp(): void
{
parent::setUp();
// Add namespaces we need for testing
Services::autoloader()->addNamespace('Tests\Support\DatabaseTestMigrations', TESTPATH . '_support/DatabaseTestMigrations');
$this->loadDependencies();
if ($this->refresh === true)
{
if (! empty($this->namespace))
{
$this->migrations->setNamespace($this->namespace);
}
$this->migrations->regress(0, 'tests');
// Delete all of the tables to ensure we're at a clean start.
$tables = $this->db->listTables();
if (is_array($tables))
{
$forge = Database::forge('tests');
foreach ($tables as $table)
{
if ($table === $this->db->DBPrefix . 'migrations')
{
continue;
}
$forge->dropTable($table, true);
}
}
$this->migrations->latest('tests');
}
if (! empty($this->seed))
{
if (! empty($this->basePath))
{
$this->seeder->setPath(rtrim($this->basePath, '/') . '/Seeds');
}
$this->seed($this->seed);
}
}
//--------------------------------------------------------------------
/**
* Takes care of any required cleanup after the test, like
* removing any rows inserted via $this->hasInDatabase()
*/
public function tearDown(): void
{
if (! empty($this->insertCache))
{
foreach ($this->insertCache as $row)
{
$this->db->table($row[0])
->where($row[1])
->delete();
}
}
}
//--------------------------------------------------------------------
/**
* Seeds that database with a specific seeder.
*
* @param string $name
*/
public function seed(string $name)
{
return $this->seeder->call($name);
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Database Test Helpers
//--------------------------------------------------------------------
/**
* Asserts that records that match the conditions in $where do
* not exist in the database.
*
* @param string $table
* @param array $where
*
* @return boolean
*/
public function dontSeeInDatabase(string $table, array $where)
{
$count = $this->db->table($table)
->where($where)
->countAllResults();
$this->assertTrue($count === 0, 'Row was found in database');
}
//--------------------------------------------------------------------
/**
* Asserts that records that match the conditions in $where DO
* exist in the database.
*
* @param string $table
* @param array $where
*
* @return boolean
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function seeInDatabase(string $table, array $where)
{
$count = $this->db->table($table)
->where($where)
->countAllResults();
$this->assertTrue($count > 0, 'Row not found in database: ' . $this->db->showLastQuery());
}
//--------------------------------------------------------------------
/**
* Fetches a single column from a database row with criteria
* matching $where.
*
* @param string $table
* @param string $column
* @param array $where
*
* @return boolean
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function grabFromDatabase(string $table, string $column, array $where)
{
$query = $this->db->table($table)
->select($column)
->where($where)
->get();
$query = $query->getRow();
return $query->$column ?? false;
}
//--------------------------------------------------------------------
/**
* Inserts a row into to the database. This row will be removed
* after the test has run.
*
* @param string $table
* @param array $data
*
* @return boolean
*/
public function hasInDatabase(string $table, array $data)
{
$this->insertCache[] = [
$table,
$data,
];
return $this->db->table($table)
->insert($data);
}
//--------------------------------------------------------------------
/**
* Asserts that the number of rows in the database that match $where
* is equal to $expected.
*
* @param integer $expected
* @param string $table
* @param array $where
*
* @return boolean
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function seeNumRecords(int $expected, string $table, array $where)
{
$count = $this->db->table($table)
->where($where)
->countAllResults();
$this->assertEquals($expected, $count, 'Wrong number of matching rows in database.');
}
//--------------------------------------------------------------------
}