i want to use PHP Unit inside a Zend Framework application. I need to make several database writing operations inside the tests.
I want to start an MySQL transaction in the setUpBeforeClass() method. That is possible, but if I try to rollback the transaction in the tearDownAfterClass() method he throws an exception with the message 'There is no active transaction'. And the test methods does the writing operations in the database.
But if i start the transaction in the test method itselfs. It works like I want.
I don't understand why it reacts like this. Knows anyone an explanation?
<?php
class ConferenceControllerTest
extends PHPUnit_Framework_TestCase
{
/**
* A database connection.
* #var Zend_Db_Adapter_Pdo_Mysql
*/
protected static $hostDb = null;
public static function setUpBeforeClass()
{
static::$hostDb = Zend_Registry::get('db_host');
static::$hostDb->beginTransaction();
// The transaction for the Adapter is activated. But not inside the tests anymore.
}
public function testTest1()
{
// At this position teh transaction is not setted anymor? Why?
static::$hostDb->beginTransaction();
$sql = 'INSERT INTO test(test) VALUES(5);';
static::$hostDb->exec($sql);
}
public static function tearDownAfterClass()
{
try
{
static::$hostDb->rollBack();
}
catch(Exception $exception)
{
$message = $exception->getMessage();
Zend_Debug::dump($message);
}
}
}
I think you may be running into phpUnit's feature to backup statics and other globals between each unit test, see the "globals" section of the Fixtures chapter of the manual
The quick-hack fix would be to add this line, in the comments just above your class:
* #backupStaticAttributes disabled
That still leaves you with the xUnit Patterns book would call a nasty smell. I'm assuming you have a few testXXX functions that you expect to run in a certain order, each depending on the result of the previous one? That requires using #depends on each function, and it is easy to get wrong.
The alternative approach is a single long unit test function, and put the DB code in setUp() and tearDown():
public function setUp()
{
$this->db = Zend_Registry::get('db_host');
$this->db->beginTransaction();
}
public function tearDown()
{
try
{
$this->db->rollBack();
}
catch(Exception $exception)
{
$message = $exception->getMessage();
Zend_Debug::dump($message);
}
public function testTestVariousDBActions()
{
$sql = 'INSERT INTO test(test) VALUES(5);';
$this->db->exec($sql);
//another DB action
$this->assertEquals(...)
//another DB action
$this->assertEquals(...)
//...
}
The advantage of this is that if any assert fails none of the subsequent ones will be attempted. But tearDown() will always be called so the database is restored.
The disadvantage could be you get a Very Long Function. Use refactoring to deal with this (e.g. if you really want each action and its test in its own function, refactor so it looks like that and have testTestVariousDBActions() call each of them in turn).
Related
In my unit tests, I am using the following getDataSet method to set up DB. the test class extends from extends PHPUnit_Extensions_Database_TestCase
It looks like the framework is not deleting the and re inserting the rows before each test. The reason I feel that way is because my tests are passing when I change the order of some of the tests, which should never happen.
So Can anyone suggest what am I doing wrong .. or where should I look further to gain more insight ?
Also, I had to use composite Data Set as some of the older fixtures are in xml format, while new fixtures are in array format. Although no xml fixtures needs for this one.
public function getDataSet()
{
$compositeDs = new PHPUnit_Extensions_Database_DataSet_CompositeDataSet();
/** #var PHPUnit_Extensions_Database_DataSet_FlatXmlDataSet $ds */
$arrayDS = new ArrayDataSet([
__DIR__ . '/seed-data/companies.php',
]);
$compositeDs->addDataSet($arrayDS);
return $compositeDs;
}
Could it be because I save pdo connection and reuse it ? as in follows
final public function getConnection()
{
if ($this->conn === null) {
if (self::$pdo == null) {
self::$pdo = new PDO($GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
}
$this->conn = $this->createDefaultDBConnection(self::$pdo, $GLOBALS['DB_DBNAME']);
}
return $this->conn;
}
getDataSet is called before every test, so every test your database-tables will be truncated and inserted with the provided data.
That's why the order of your tests doesn't matter.
Lately I'm giving a try to phpspec. It works great, but I have got a problem with testing command handlers. For example in PHPUnit I test it that way:
/**
* #test
*/
public function it_should_change_an_email()
{
$this->repository->add($this->employee);
$this->handler->changeEmail(
new ChangeEmailCommand(
$this->employee->username()->username(),
'new#email.com'
)
);
Asserts::assertEquals(new Email('new#email.com'), $this->employee->email());
}
and setup:
protected function setUp()
{
$this->repository = new InMemoryEmployeeRepository();
$this->createEmployee();
$this->handler = new EmployeeCommandHandler($this->repository);
}
The main point is that this test make assertions on the Employee object to check if CommandHandler is working good. But in phpspec I can't make assertion on different object than the specifying one, in this case I can only make assertion on my CommandHandler. So how I can test a command handler in phpspec?
EDIT
Maybe spies are the way to go:
class EmployeeCommandHandlerSpec extends ObjectBehavior
{
const USERNAME = 'johnny';
/** #var EmployeeRepository */
private $employeeRepository;
public function let(EmployeeRepository $employeeRepository)
{
$this->employeeRepository = $employeeRepository;
$this->beConstructedWith($employeeRepository);
}
public function it_changes_the_employee_email(Employee $employee)
{
$this->givenEmployeeExists($employee);
$this->changeEmail(
new ChangeEmailCommand(self::USERNAME, 'new#email.com')
);
$employee->changeEmail(new Email('new#email.com'))->shouldHaveBeenCalled();
}
private function givenEmployeeExists(Employee $employee)
{
$this->employeeRepository->employeeWithUsername(new EmployeeUsername(self::USERNAME))
->shouldBeCalled()
->willReturn($employee);
}
}
Employee class I've already speced. So, maybe, in command handler it'll be enough to just check if the method of the Employee has been called. What do you think about it? Am I going in good direction?
Messaging
Indeed, you shouldn't verify the state, but expect certain interactions between objects. That's what OOP is about afterall - messaging.
The way you've done it in PHPUnit is state verification. It forces you to expose the state as you need to provide a "getter", which is not always desired. What you're interested in is that Employee's email was updated:
$employee->updateEmail(new Email('new#email.com'))->shouldBeCalled();
The same can be achieved with spies if you prefer:
$employee->updateEmail(new Email('new#email.com'))->shouldHaveBeenCalled();
Command/Query Separation
We usually only need to state our expectations against methods that have side effects (command methods from Command/Query separation). We mock them.
Query methods do not need to be mocked, but stubbed. You don't really expect that EmployeeRepository::employeeWithUsername() should be called. Doing so we're making assumptions about implementation which in turn will make refactoring harder. All you need is stubbing it, so if a method is called it returns a result:
$employeeRepository->employeeWithUsername(new EmployeeUsername(self::USERNAME))
->willReturn($employee);
Full example
class EmployeeCommandHandlerSpec extends ObjectBehavior
{
const USERNAME = 'johnny';
public function let(EmployeeRepository $employeeRepository)
{
$this->beConstructedWith($employeeRepository);
}
public function it_changes_the_employee_email(
EmployeeRepository $employees, Employee $employee
) {
$this->givenEmployeeExists($employees, $employee);
$this->changeEmail(
new ChangeEmailCommand(self::USERNAME, 'new#email.com')
);
$employee->changeEmail(new Email('new#email.com'))->shouldHaveBeenCalled();
}
private function givenEmployeeExists(
EmployeeRepository $employees, Employee $employee
) {
$employees->employeeWithUsername(new EmployeeUsername(self::USERNAME))
->willReturn($employee);
}
}
Is is possible in PHP to trigger an event whenever a function in a class is called, without adding it to every function in the class?
Example:
<?php
class A {
function xxx() {
//this function will be called everytime I call another function in this class
}
public static function b() {
return 'Hello Stackoverflow!';
}
public static function c() {
//I also want this function to trigger the event!
}
}
echo A::b();
?>
AFAIK there are no native language constructs for this. If you need it for debugging purposes I would advice you to have deeper look into the xdebug extension especially function traces (awesome! :)
Another idea would be to implement __call() in your class and wrap all public methods. But this requires to change the code and has other side effects:
(simplified example)
class Test {
protected $listeners;
public function __construct() {
$this->listeners = array();
}
private function a() {
echo 'something';
}
private function b() {
echo 'something else';
}
public function __call($fname, $args) {
call_user_func_array(array($this, $fname), $args);
foreach($this->listeners as $listener) {
$listener->notify('fname was called');
}
}
public function addListener(Listener $listener) {
$this->listeners[]= $listener;
}
}
.
class Listener {
public function notify($message) {
echo $message;
}
}
Example:
$t = new Test();
$l = new Listener();
$t->addListener($l);
$t->a();
This is a classic task for aspect oriented programming (AOP). PHP has no native support for AOP, however, there are some frameworks that make AOP in PHP possible. One of these is the GO! AOP PHP framework. You can also implement AOP using runkit.
You need for PHP SplObserver: From PHP Doc
This is a classic task for dependency injection and lazy initialization! The dependency is the MySQL connection. As it first needs to be available when the first query is executed, it need not be initialized at "startup", but only then. This is called lazy initialization, and its implementation is extremly simple:
class DbStuff {
private $__conn = NULL;
protected function _getConn() {
if ( is_null( $this->__conn ) {
$this->__conn = ... ; // init (MySQL) DB connection here
// throw on errors!
}
return $this->__conn;
}
public function someQuery($arg1, $arg2) {
$conn = $this->_getConn();
// MySQL query here:
...
}
}
All "refactoring" required is calling $this->_getConn() in every query method.
Aspect oriented programming is not the instrument to solve this, because the DB connection is an innate dependency of the query, and not an aspect of it. Automatic logging of all queries executed were an aspect.
A trigger built around PHP's __call() isn't a good choice either; aside from knocking out modern IDE's inspections - which are great to see quickly whether a module is fine - it would unnecessarily complicate tests: a protected $this->_getWhatever() can easily be overwritten in a test facade object - derived from the class to test - to return a mock object or whatever. With __call(), more code is needed for the same purpose, which induces the risk of errors in code which is only there for testing (and should be absolutely free of errors)
I'm having difficulty mocking the PDO object with PHPUnit.
There doesn't seem to be much information on the web about my problem but from what I can gather:
PDO has 'final' __wakeup and
__sleep methods that prevent it from being serialised.
PHPunit's mock object implementation serialises the object at some point.
The unit tests then fail with a PHP error generated by PDO when this occurs.
There is a feature meant to prevent this behavior, by adding the following line to your unit test:
class MyTest extends PHPUnit_Framework_TestCase
{
protected $backupGlobals = FALSE;
// ...
}
Source: http://sebastian-bergmann.de/archives/797-Global-Variables-and-PHPUnit.html
This isnt working for me, my test still produces an error.
Full test code:
class MyTest extends PHPUnit_Framework_TestCase
{
/**
* #var MyTest
*/
private $MyTestr;
protected $backupGlobals = FALSE;
/**
* Prepares the environment before running a test.
*/
protected function setUp()
{
parent::setUp();
}
/**
* Cleans up the environment after running a test.
*/
protected function tearDown()
{
parent::tearDown();
}
public function __construct()
{
$this->backupGlobals = false;
parent::__construct();
}
/**
* Tests MyTest->__construct()
*/
public function test__construct()
{
$pdoMock = $this->getMock('PDO', array('prepare'), array(), '', false);
$classToTest = new MyTest($pdoMock);
// Assert stuff here!
}
// More test code.......
Any PHPUnit pro's give me a hand?
Thanks,
Ben
$backupGlobals does not help you, because this error comes from elsewhere. PHPUnit 3.5.2 (possibly earlier versions as well) has the following code in PHPUnit/Framework/MockObject/Generator.php
if ($callOriginalConstructor &&
!interface_exists($originalClassName, $callAutoload)) {
if (count($arguments) == 0) {
$mockObject = new $mock['mockClassName'];
} else {
$mockClass = new ReflectionClass($mock['mockClassName']);
$mockObject = $mockClass->newInstanceArgs($arguments);
}
} else {
// Use a trick to create a new object of a class
// without invoking its constructor.
$mockObject = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($mock['mockClassName']), $mock['mockClassName']
)
);
}
This "trick" with unserialize is used when you ask getMock to not execute the original constructor and it will promptly fail with PDO.
So, how do work around it?
One option is to create a test helper like this
class mockPDO extends PDO
{
public function __construct ()
{}
}
The goal here is to get rid of the original PDO constructor, which you do not need. Then, change your test code to this:
$pdoMock = $this->getMock('mockPDO', array('prepare'));
Creating mock like this will execute original constructor, but since it is now harmless thanks to mockPDO test helper, you can continue testing.
The best I can think of is to use runkit and redefine the two final methods as protected using runkit_function_redefine.
Dont for get to enable the runkit.internal_override setting in php.ini.
And as ever, as with eval, if runkit seems like the answer, the question is probably wrong :)
You are instantiating your test case in your test case?
$classToTest = new MyTest($pdoMock);
Right now, you are essentially testing your test case. It should be more something like:
$classToTest = new My($pdoMock);
Below I present three options for simplifying my database access when only a single connection is involved (this is often the case for the web apps I work on).
The general idea is to make the DB connection transparent, such that it connects the first time my script executes a query, and then it remains connected until the script terminates.
I'd like to know which one you think is the best and why. I don't know the names of any design patterns that these might fit so sorry for not using them. And if there's any better way of doing this with PHP5, please share.
To give a brief introduction: there is a DB_Connection class containing a query method. This is a third-party class which is out of my control and whose interface I've simplified for the purpose of this example. In each option I've also provided an example model for an imaginary DB "items" table to give some context.
Option 3 is the one that provides me with the interface I like most, but I don't think it's practical unfortunately.
I've described the pros and cons (that I can see) of each in the comment blocks below.
At the moment I lean towards Option 1 since the burden is put on my DB wrapper class instead of on the models.
All comments appreciated!
Note: For some reason, the Stack Overflow preview is showing an encoded HTML entity instead of underscores. If the post comes through like that, please take this into account.
<?php
/**
* This is the 3rd-party DB interface I'm trying to wrap.
* I've simplified the interface to one method for this example.
*
* This class is used in each option below.
*/
class DB_Connection {
public function &query($sql) { }
}
/**
* OPTION 1
*
* Cons: Have to wrap every public DB_Connection method.
* Pros: The model code is simple.
*/
class DB {
private static $connection;
private static function &getConnection() {
if (!self::$connection) {
self::$connection = new DB_Connection();
}
return self::$connection;
}
public static function &query($sql) {
$dbh = self::getConnection();
return $dbh->query($sql);
}
}
class Item {
public static function &getList() {
return DB::query("SELECT * FROM items");
}
}
/**
* OPTION 2
*
* Pros: Don't have to wrap every DB_Connection function like in Option 1
* Cons: Every function in the model is responsible for checking the connection
*/
class DB {
protected static $connection = null;
public function connect() {
self::$connection = new DB_Connection();
}
}
class Item extends DB {
public static function &getList() {
if (!self::$connection) $this->connect();
return self::$connection->query("SELECT * FROM items");
}
}
/**
* OPTION 3
*
* Use magic methods
*
* Pros: Simple model code AND don't have to reimplement the DB_Connection interface
* Cons: __callStatic requires PHP 5.3.0 and its args can't be passed-by-reference.
*/
class DB {
private static $connection = null;
public static function &getConnection() {
if (!self::$connection) {
self::$connection = new DB_Connection();
}
return self::$connection;
}
public static function __callStatic($name, $args) {
if (in_array($name, get_class_methods('DB_Connection'))) {
return call_user_func_array(
array(self::getConnection(), $name), $args);
}
}
}
Based on your examples above, I'd say option 1 is the best - simplicity always wins, and you can handle a failed connection differently depending on the method (you might want to fail differently for a stored procedure call than a simple SELECT, for instance).
Semantically speaking I think option 1 makes the most sense, if you're treating DB as a resource then the DB_Connectioin is an object that it uses but not necessarily the object itself.
However, several things I caution you against. First, don't make your DB class have all static methods as it will strongly impact your ability to test your code. Consider instead a very simple inversion of control container like this:
class DB {
private $connection;
public function &query($sql) {
return $connection->query($sql);
}
public __construct(&$db_connection) {
$this->connection = $db_connection;
}
}
class Item {
public function &getList() {
return ResourceManager::getDB()->query("SELECT * FROM items");
}
}
class ResourceManager {
private $db_connection;
private function &getDbConnection() {
if (!$this->connection) {
$this->connection = new DB_Connection();
}
return $this->connection;
}
private $db;
public static function getDB() {
if(!$this->db) $this->db = new DB(getDbConnection());
return $this->db;
}
There are significant benefits. If you don't want DB to be used as a singleton you just make one modification to ResourceManager. If you decide it should not be a singleton - you make the modification in one place. If you want to return a different instance of DB based on some context - again, the change is in only one place.
Now if you want to test Item in isolation of DB simply create a setDb($db) method in ResourceManager and use it to set a fake/mock database (simplemock will serve you well in that respect).
Second - and this is another modification that this design eases - you might not want to keep your database connection open the entire time, it can end up using far more resources than need be.
Finally, as you mention that DB_Connection has other methods not shown, it seems like the it might be being used for more than simply maintaining a connection. Since you say you have no control over it, might I recommend extracting an interface from it of the methods that you DO care about and making a MyDBConnection extends DB_Connection class that implements your interface. In my experience something like that will ultimately ease some pain as well.