Unit-testing with CakePhP and PHPUnit - unit-testing

I`m trying to do unit-testing with CakePhP 2.3 and PHPUnit 2.7. I want to test the index function in my customer’s controller.
In my controller I have:
public function index() {
$this->Customer->recursive = -1;
$data = $this->paginate('Customer', array( 'Customer.status'=>'active'));
$this->set('customers', $data);
}
I tried to follow the examples in book.cakephp.org, so I created Fixture class in which I`m importing the Customer schema and all the records.
class CustomerFixture extends CakeTestFixture{
public $import = array('model' => 'Customer', 'records' => true);
}
And finally my test class looks like this:
class CustomersControllerTest extends ControllerTestCase {
public $fixtures = array('app.customer');
public function testIndex() {
$result = $this->testAction('/customers/index');
debug($result);
}
}
When I run my test I have the following error:
Database Error
Error: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '8' for key 'PRIMARY'
Do you have any ideas what can be the problem?

In your database.php in app/Config folder you have to add a $test variable.
For example
class DATABASE_CONFIG {
public $default = array(
'datasource' => 'Database/Mysql',
'persistent' => true,
'host' => 'localhost',
'port' => 3306,
'login' => 'root',
'password' => 'xxxx',
'database' => 'mydatabase',
'encoding' => 'utf8'
);
public $test = array(
'datasource' => 'Database/Mysql',
'persistent' => false,
'host' => 'localhost',
'port' => 3306,
'login' => 'root',
'password' => 'xxxx',
'database' => 'mydatabase_test',
'encoding' => 'utf8'
);
}
Then your unit testing will use the mydatabase_test for testing your code. Because now it uses the default database.

Related

Silex DoctrineServiceProvider not connecting

I'am building application on Silex, and I'am having some problems on very basic stuff. I used example from official documentation for using doctrine service provider, but no matter what i do $app[ 'db' ]->isConnected() returns false. Here is the code
$app = new Application();
$app->register(new DoctrineServiceProvider(), array(
'dbs.options' => array (
'mysql' => array(
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'sevenbet',
'user' => 'root',
'password' => '',
'charset' => 'utf8',
)
),
));
Don't use multi dimension array, if you have one db config to provide, just use :
$app['db.options'] = array (
'driver' => 'pdo_mysql',
'host' => 'localhost',
'dbname' => 'mydb',
'user' => 'root',
'password' => 'root',
'charset' => 'utf8'
);

get doctrine db config in zf2

I want to use doctrine db config to access to DBAL layer in doctrine, I have the following configuration in my doctrine db file config:
database.local.php
return array(
'doctrine' => array(
'connection' => array(
'orm_default' => array(
'driverClass' => 'Doctrine\DBAL\Driver\PDOPgSql\Driver',
'params' => array(
'host' => 'localhost',
'port' => '5432',
'user' => 'postgres',
'password' => '123456',
'dbname' => 'test'
)
)
)
)
);
and in my controller
IndexController.php
use Doctrine\DBAL\DriverManager;
public function testAction(){
$conn = DriverManager::getConnection($params, $config);
}
I want to use db config above in the getConnection function, is this possible?
If you've a db configuration in your local.php, so why don't you access it through the EntityManager ? Just like this :
public function testAction(){
$em = ->getServiceLocator()
->get('Doctrine\ORM\EntityManager');
$conn = $em->getConnection();
}
If you want to get it through the DriverManager :
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = array(
'host' => 'localhost',
'port' => '5432',
'user' => 'postgres',
'password' => '123456',
'dbname' => 'test'
'driver' => 'pdo_pgsql',
);
$conn = DriverManager::getConnection($connectionParams, $config);
EDIT :
You can also get directly an instance of Doctrine\DBAL\Connection using the Registered Service names provided by Doctrine with your actual db configuration :
$conn = $this->getServiceLocator()->get('doctrine.connection.orm_default');
As the DriverManager::getConnection() method, this will return a Doctrine\DBAL\Connection which wraps the underlying driver connection.
Sure.
First of all you should use ServiceLocator
ServiceLocator are auto injected into classes that implements \Zend\ServiceManager\ServiceLocatorAwareInterface
AbstractActionController, of your zf2 controllers already implements this interface.
To use into a class (model by example) you should declare implements and two methods that are designed by interface, setServiceLocator and getServiceLocator.
<?php
namespace Security\Repository;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
class Repository implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
Using ServiceLocator are easy to do anything on ZF2. Try To understand how it works to get the fully power of zf2.
$configArray = $this->getServiceLocator()->get('config');
$config = new \Doctrine\DBAL\Configuration();
$connectionParams = $configArray['doctrine']['connection']['orm_default']['params']
$conn = DriverManager::getConnection($connectionParams, $config);

laravel enviroment when on command line different to in browser

I have deployed my laravel app to an elastic beanstalk enviroment. This app detects its environment with this piece of code in bootstrap/start.php
$env = $app->detectEnvironment(function () {
return getenv('APP_ENV') ?: 'local';
});
When elastic beanstalk starts it runs its configuration files which I have set up to detect if a parameter is set. in this case I have set this parameter to development and the configuration files then set enviroment variables based on this namely
APP_ENV = development
DB_HOST = rds dev endpoint
DB_NAME = rds dev db name
DB_USERNAME = dev username
DB_PASSWORD = devdb pass
When I visit the app in the browser it is working as intended and it is correctly connecting to the dev db.
When I ssh into the server and try to run
php artisan migrate
I get a pdo exception no such file or directory
when I run
php artisan env
local is returned even though the environment variable APP_ENV is defined. I am doubly sure that this variable is defined because when laravel errors in the browser I can see the variable with the value development in the server/request data along with the other environment variables that are created on environment launch
what am I missing?
edited to include personalised solution based on antonios answer
.environment
<?php
if (getenv('PARAM1') === false) {
return false;
} else {
switch (getenv('PARAM1')) {
case 'development':
return array(
'APP_ENV' => 'development',
'DB_HOST' => '***',
'DB_NAME' => '***',
'DB_USERNAME' => '***',
'DB_PASSWORD' => '***',
);
break;
case 'staging':
return array(
'APP_ENV' => 'staging',
'DB_HOST' => '***',
'DB_NAME' => '***',
'DB_USERNAME' => '***',
'DB_PASSWORD' => '***',
);
break;
case 'production':
return array(
'APP_ENV' => 'production',
'DB_HOST' => '***',
'DB_NAME' => '***',
'DB_USERNAME' => '***',
'DB_PASSWORD' => '***',
);
break;
}
}
start.php
$env = require __DIR__.'/../.environment';
if ($env !== false) {
foreach ($env as $key => $value) {
putenv(sprintf('%s=%s', $key, $value));
}
}
$env = $app->detectEnvironment(function () {
return getenv('APP_ENV') ?: 'local';
});
When you run
php artisan migrate
php runs under a different user, not your web server, so you need to:
php artisan migrate --env=development
EDIT
Having trouble with cli and web is one of the reasons why I don't use those web servers env vars. This is how I do my environments:
Create a .environment file in the root of your application and define your environment:
<?php
return array(
'APP_ENV' => 'development',
'POSTGRESQL.HOST' => 'localhost',
'POSTGRESQL.DATABASE_NAME' => 'laraveldatabase',
'POSTGRESQL.DATABASE_USER' => 'laraveluser',
'POSTGRESQL.DATABASE_PASSWORD' => '!Bassw0rT',
);
Add it to your .gitignore application file, so you don't risk having your passwords sent to Github.
Right before $app->detectEnvironment, load the .environment file to PHP environment:
foreach(require __DIR__.'/../.environment' as $key => $value)
{
putenv(sprintf('%s=%s', $key, $value));
}
And then you just have to use it:
$env = $app->detectEnvironment(function () {
return getenv('APP_ENV');
});
It will work everywhere:
<?php
return array(
'connections' => array(
'postgresql' => array(
'driver' => 'pgsql',
'host' => getenv('POSTGRESQL.HOST'),
'database' => getenv('POSTGRESQL.DATABASE_NAME'),
'username' => getenv('POSTGRESQL.DATABASE_USER'),
'password' => getenv('POSTGRESQL.DATABASE_PASSWORD'),
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
),
),
);
Note that I don't do
return getenv('APP_ENV') ?: 'local';
Because I want it to fail on every server I deploy my app to.

Laravel Queue::shouldReceive()

I have the following in one of my routes
$rules = array(
'name' => 'Required',
'subject' => 'Required',
'message' => 'Required',
'email' => 'Required|Email',
'recaptcha_response_field' => 'required|recaptcha'
);
$validator = Validator::make(Input::all(), $rules);
if($validator->fails()){
return Redirect::to('contact')->withInput()->withErrors($validator);
}else{
$data = array('name' => Input::get('name'),
'email' => Input::get('email'),
'text' => Input::get('message'),
'subject' => Input::get('subject'));
Queue::push('ContactQueue', $data);
return Redirect::to('contact')->with('success', 'Message sent successfully');
}
I am trying to write a unit test for the success scenario, I have the following:
public function testSuccess(){
Validator::shouldReceive('make')->once()->andReturn(Mockery::mock(['fails' => false]));
Queue::shouldReceive('push')->once();
$this->call('POST', '/contact');
$this->assertRedirectedTo('/contact');
}
But I keep receiving the following error when trying to run phpunit:
BadMethodCallException: Method Illuminate\Queue\QueueManager::connected() does not exist on this mock object
Any ideas?
Putting Queue::shouldReceive('connected')->once();
after Queue::shouldReceive('push')->once();
solved this.

How to create database in doctrine 2

I would like to create a database with doctrine 2 and zend framework 2.
I tried to use the command line but it doesn't work because first of all I need to be connected to a database.
Here is the command line that I could use :
When I use the command "php doctrine dbal:run-sql CREATE DATABASE TOTO", I receive an error which tells me that I the database that I selected (but I don't want to select any database) is unknown.
Do you have any idea how I can figure out this problem ?
I really appreciate if I not obliged to use phpmyadmin and create it by my own. I'll prefer to use doctrine to make sure that my code is compatible with other kind of database (such as Mysql/Postegre)
Thank you =D
I found the solution.
You just have to specify in your configuration file that the dbname is equals to null.
<?php
return array (
'doctrine' => array (
'connection' =>
array (
'orm_default' =>
array (
'driverClass' => 'Doctrine\\DBAL\\Driver\\PDOMySql\\Driver',
'params' =>
array (
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => '',
'dbname' => null,
'charset' => 'UTF8',
),
),
'orm_poems' =>
array (
'driverClass' => 'Doctrine\\DBAL\\Driver\\PDOMySql\\Driver',
'params' =>
array (
'host' => 'localhost',
'port' => '3306',
'user' => 'root',
'password' => 'mot de passe',
'dbname' => 'poemsV3',
'charset' => 'UTF8',
),
),
),
),
);
Have a good day everybody =D