We do not want to use "@backupStaticAttributes enabled"

refs #4639
This commit is contained in:
Johannes Meyer 2014-04-11 15:31:29 +02:00
parent f3c87782cb
commit 927772578d
18 changed files with 106 additions and 145 deletions

View File

@ -25,31 +25,41 @@ modules/mymodule/library/MyModule/Helper/MyClass.php.
## Testing Singletons ## Testing Singletons
When test methods **modify static** class properties (which is the case when using singletons), add the PHPUnit When test methods **modify static** class properties (which is the case when using singletons), do not add the PHPUnit
[`@backupStaticAttributes enabled`](http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.backupStaticAttributes) [`@backupStaticAttributes enabled`](http://phpunit.de/manual/3.7/en/appendixes.annotations.html#appendixes.annotations.backupStaticAttributes)
annotation to their [DockBlock](http://www.phpdoc.org/docs/latest/for-users/phpdoc/basic-syntax.html#what-is-a-docblock) annotation to their [DocBlock](http://www.phpdoc.org/docs/latest/for-users/phpdoc/basic-syntax.html#what-is-a-docblock)
in order to backup and restore static attributes before and after the method execution respectively. For reference you in order to backup and restore static attributes before and after the test execution respectively. Use the setUp()
should **document** that the test interacts with static attributes: and tearDown() routines instead to accomplish this task.
<?php <?php
namespace My\Test; namespace My\Test;
use \PHPUnit_Framework_TestCase; use Icinga\Test\BaseTestCase;
use My\CheesecakeFactory; use My\CheesecakeFactory;
class SingletonTest extends PHPUnit_Framework_TestCase class SingletonTest extends BaseTestCase
{ {
/** protected function setUp()
* Interact with static attributes {
* parent::setUp();
* Utilizes singleton CheesecakeFactory $this->openingHours = CheesecakeFactory::getOpeningHours();
* }
* @backupStaticAttributes enabled
*/ protected function tearDown()
{
parent::tearDown();
CheesecakeFactory::setOpeningHours($this->openingHours);
}
public function testThatInteractsWithStaticAttributes() public function testThatInteractsWithStaticAttributes()
{ {
CheesecakeFactory::setOpeningHours(24); CheesecakeFactory::setOpeningHours(24);
// ... // ...
} }
} }
The reason to avoid using @backupStaticAttributes is the fact that if it is necessary to utilize a
singleton in your *unit* tests you probably want to rethink what you are going to test and because
some tests are using the mock framework [`Mockery`](https://github.com/padraic/mockery) which is
using static class properties to implement its caching mechanics.

View File

@ -22,9 +22,12 @@ namespace {
namespace Icinga\Test { namespace Icinga\Test {
use \Exception; use \Exception;
use \DateTimeZone;
use \RuntimeException; use \RuntimeException;
use \Mockery;
use \Zend_Config; use \Zend_Config;
use \Zend_Test_PHPUnit_ControllerTestCase; use \Zend_Test_PHPUnit_ControllerTestCase;
use Icinga\Util\DateTimeFactory;
use Icinga\Data\ResourceFactory; use Icinga\Data\ResourceFactory;
use Icinga\Data\Db\Connection; use Icinga\Data\Db\Connection;
use Icinga\User\Preferences; use Icinga\User\Preferences;
@ -104,17 +107,12 @@ namespace Icinga\Test {
); );
/** /**
* Constructs a test case with the given name. * Setup the default timezone and pass it to DateTimeFactory::setConfig
*
* @param string $name
* @param array $data
* @param string $dataName
* @see PHPUnit_Framework_TestCase::__construct
*/ */
public function __construct($name = null, array $data = array(), $dataName = '') public static function setupTimezone()
{ {
parent::__construct($name, $data, $dataName);
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
} }
/** /**
@ -124,12 +122,6 @@ namespace Icinga\Test {
*/ */
public static function setupDirectories() public static function setupDirectories()
{ {
static $initialized = false;
if ($initialized === true) {
return;
}
$baseDir = realpath(__DIR__ . '/../../../'); $baseDir = realpath(__DIR__ . '/../../../');
if ($baseDir === false) { if ($baseDir === false) {
@ -142,8 +134,38 @@ namespace Icinga\Test {
self::$testDir = $baseDir . '/test/php'; self::$testDir = $baseDir . '/test/php';
self::$shareDir = $baseDir . '/share/icinga2-web'; self::$shareDir = $baseDir . '/share/icinga2-web';
self::$moduleDir = $baseDir . '/modules'; self::$moduleDir = $baseDir . '/modules';
}
$initialized = true; /**
* Setup MVC bootstrapping and ensure that the Icinga-Mock gets reinitialized
*/
public function setUp()
{
parent::setUp();
$this->setupIcingaMock();
}
/**
* Setup mock object for Icinga\Application\Icinga
*
* Once done, the original class can never be loaded anymore though one should still be able
* to access its properties/methods not covered by any expectations by using the mock object.
*/
protected function setupIcingaMock()
{
$bootstrapMock = Mockery::mock('Icinga\Application\ApplicationBootstrap')->shouldDeferMissing();
$bootstrapMock->shouldReceive('getFrontController->getRequest')->andReturnUsing(
function () {
return Mockery::mock('Request')
->shouldReceive('getPathInfo')->andReturn('')
->shouldReceive('getBaseUrl')->andReturn('/')
->shouldReceive('getQuery')->andReturn(array())
->getMock();
}
)->shouldReceive('getApplicationDir')->andReturn(self::$appDir);
Mockery::mock('alias:Icinga\Application\Icinga')
->shouldReceive('app')->andReturnUsing(function () use ($bootstrapMock) { return $bootstrapMock; });
} }
/** /**
@ -154,7 +176,7 @@ namespace Icinga\Test {
* @return Zend_Config * @return Zend_Config
* @throws RuntimeException * @throws RuntimeException
*/ */
private function createDbConfigFor($name) protected function createDbConfigFor($name)
{ {
if (array_key_exists($name, self::$dbConfiguration)) { if (array_key_exists($name, self::$dbConfiguration)) {
return new Zend_Config(self::$dbConfiguration[$name]); return new Zend_Config(self::$dbConfiguration[$name]);
@ -170,7 +192,7 @@ namespace Icinga\Test {
* *
* @return array * @return array
*/ */
private function createDbConnectionFor($name) protected function createDbConnectionFor($name)
{ {
try { try {
$conn = ResourceFactory::createResource($this->createDbConfigFor($name)); $conn = ResourceFactory::createResource($this->createDbConfigFor($name));
@ -306,5 +328,6 @@ namespace Icinga\Test {
} }
} }
BaseTestCase::setupTimezone();
BaseTestCase::setupDirectories(); BaseTestCase::setupDirectories();
} }

View File

@ -4,26 +4,12 @@
namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command;
use \DateTimeZone;
use Icinga\Test\BaseTestCase; use Icinga\Test\BaseTestCase;
use Icinga\Util\DateTimeFactory;
class AcknowledgeFormTest extends BaseTestCase class AcknowledgeFormTest extends BaseTestCase
{ {
const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\AcknowledgeForm'; const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\AcknowledgeForm';
/**
* Set DateTimeFactory's time zone to UTC
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/
public function setUp()
{
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
}
public function testFormValid() public function testFormValid()
{ {
$form = $this->createForm( $form = $this->createForm(

View File

@ -4,26 +4,12 @@
namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command;
use \DateTimeZone;
use Icinga\Test\BaseTestCase; use Icinga\Test\BaseTestCase;
use Icinga\Util\DateTimeFactory;
class RescheduleNextCheckFormTest extends BaseTestCase class RescheduleNextCheckFormTest extends BaseTestCase
{ {
const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\RescheduleNextCheckForm'; const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\RescheduleNextCheckForm';
/**
* Set DateTimeFactory's time zone to UTC
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/
public function setUp()
{
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
}
public function testFormInvalidWhenChecktimeIsIncorrect() public function testFormInvalidWhenChecktimeIsIncorrect()
{ {
$form = $this->createForm( $form = $this->createForm(

View File

@ -4,27 +4,13 @@
namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command; namespace Tests\Icinga\Module\Monitoring\Application\Forms\Command;
use \DateTimeZone;
use Icinga\Test\BaseTestCase; use Icinga\Test\BaseTestCase;
use Icinga\Util\DateTimeFactory;
use Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm; use Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm;
class ScheduleDowntimeFormTest extends BaseTestCase class ScheduleDowntimeFormTest extends BaseTestCase
{ {
const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm'; const FORM_CLASS = 'Icinga\Module\Monitoring\Form\Command\ScheduleDowntimeForm';
/**
* Set up the default time zone
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/
public function setUp()
{
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
}
public function testCorrectFormElementCreation() public function testCorrectFormElementCreation()
{ {
$formFixed = $this->createForm(self::FORM_CLASS); $formFixed = $this->createForm(self::FORM_CLASS);

View File

@ -11,16 +11,23 @@ class ConfigTest extends BaseTestCase
{ {
/** /**
* Set up config dir * Set up config dir
*
* Utilizes singleton IcingaConfig
*
* @backupStaticAttributes enabled
*/ */
public function setUp() public function setUp()
{ {
parent::setUp();
$this->configDir = IcingaConfig::$configDir;
IcingaConfig::$configDir = dirname(__FILE__) . '/Config/files'; IcingaConfig::$configDir = dirname(__FILE__) . '/Config/files';
} }
/**
* Reset config dir
*/
public function tearDown()
{
parent::tearDown();
IcingaConfig::$configDir = $this->configDir;
}
public function testAppConfig() public function testAppConfig()
{ {
$config = IcingaConfig::app(); $config = IcingaConfig::app();

View File

@ -27,16 +27,18 @@ class TestStruct
EOD; EOD;
protected function setUp() public function setUp()
{ {
parent::setUp();
$tempDir = sys_get_temp_dir(); $tempDir = sys_get_temp_dir();
$this->baseDir = tempnam($tempDir, 'icinga2-web'); $this->baseDir = tempnam($tempDir, 'icinga2-web');
system('mkdir -p '. $this->baseDir. dirname(self::$classFile)); system('mkdir -p '. $this->baseDir. dirname(self::$classFile));
file_put_contents($this->baseDir. self::$classFile, self::$classContent); file_put_contents($this->baseDir. self::$classFile, self::$classContent);
} }
protected function tearDown() public function tearDown()
{ {
parent::tearDown();
system('rm -rf '. $this->baseDir); system('rm -rf '. $this->baseDir);
} }

View File

@ -10,14 +10,11 @@ use Icinga\Test\BaseTestCase;
class LoggerTest extends BaseTestCase class LoggerTest extends BaseTestCase
{ {
/**
* @backupStaticAttributes enabled
*/
public function testLogfileCreation() public function testLogfileCreation()
{ {
$target = tempnam(sys_get_temp_dir(), 'log'); $target = tempnam(sys_get_temp_dir(), 'log');
unlink($target); unlink($target);
Logger::create( new Logger(
new Zend_Config( new Zend_Config(
array( array(
'enable' => true, 'enable' => true,
@ -32,14 +29,13 @@ class LoggerTest extends BaseTestCase
} }
/** /**
* @backupStaticAttributes enabled
* @depends testLogfileCreation * @depends testLogfileCreation
*/ */
public function testLoggingErrorMessages() public function testLoggingErrorMessages()
{ {
$target = tempnam(sys_get_temp_dir(), 'log'); $target = tempnam(sys_get_temp_dir(), 'log');
unlink($target); unlink($target);
Logger::create( $logger = new Logger(
new Zend_Config( new Zend_Config(
array( array(
'enable' => true, 'enable' => true,
@ -49,7 +45,7 @@ class LoggerTest extends BaseTestCase
) )
) )
); );
Logger::error('This is a test error'); $logger->log('This is a test error', Logger::$ERROR);
$log = file_get_contents($target); $log = file_get_contents($target);
unlink($target); unlink($target);
$this->assertContains('This is a test error', $log, 'Log does not contain the error "This is a test error"'); $this->assertContains('This is a test error', $log, 'Log does not contain the error "This is a test error"');

View File

@ -27,8 +27,10 @@ class ManagerTest extends BaseTestCase
{ {
const MODULE_TARGET = "/tmp"; const MODULE_TARGET = "/tmp";
protected function setUp() public function setUp()
{ {
parent::setUp();
$moduleDir = self::MODULE_TARGET; $moduleDir = self::MODULE_TARGET;
if (!is_writable($moduleDir)) { if (!is_writable($moduleDir)) {
$this->markTestSkipped("Temporary folder not writable for this user"); $this->markTestSkipped("Temporary folder not writable for this user");
@ -98,8 +100,9 @@ class ManagerTest extends BaseTestCase
$this->assertEmpty($manager->listEnabledModules()); $this->assertEmpty($manager->listEnabledModules());
} }
protected function tearDown() public function tearDown()
{ {
parent::tearDown();
$moduleDir = self::MODULE_TARGET; $moduleDir = self::MODULE_TARGET;
exec("rm -r $moduleDir/enabledModules"); exec("rm -r $moduleDir/enabledModules");
} }

View File

@ -86,8 +86,10 @@ class LdapUserBackendTest extends BaseTestCase
} }
} }
protected function setUp() public function setUp()
{ {
parent::setUp();
$conn = $this->getLDAPConnection(); $conn = $this->getLDAPConnection();
$this->clearTestData($conn); $this->clearTestData($conn);
$this->insertTestData($conn); $this->insertTestData($conn);
@ -109,6 +111,7 @@ class LdapUserBackendTest extends BaseTestCase
public function tearDown() public function tearDown()
{ {
parent::tearDown();
$conn = $this->getLDAPConnection(); $conn = $this->getLDAPConnection();
// $this->clearTestData($conn); // $this->clearTestData($conn);

View File

@ -17,6 +17,8 @@ class PreservingIniWriterTest extends BaseTestCase
*/ */
public function setUp() public function setUp()
{ {
parent::setUp();
$ini = $ini =
' '
trailing1="wert" trailing1="wert"
@ -109,6 +111,7 @@ prop2="5"
*/ */
public function tearDown() public function tearDown()
{ {
parent::tearDown();
foreach ($this->tmpfiles as $filename) { foreach ($this->tmpfiles as $filename) {
unlink($filename); unlink($filename);
} }

View File

@ -45,8 +45,9 @@ class ParserMock
class ReaderTest extends BaseTestCase class ReaderTest extends BaseTestCase
{ {
protected function tearDown() public function tearDown()
{ {
parent::tearDown();
if (file_exists('./tmp')) { if (file_exists('./tmp')) {
@system("rm -rf ./tmp"); @system("rm -rf ./tmp");
} }

View File

@ -10,8 +10,9 @@ class BaseTestCaseDbTest extends BaseTestCase
{ {
private $emptySqlDumpFile; private $emptySqlDumpFile;
protected function tearDown() public function tearDown()
{ {
parent::tearDown();
if ($this->emptySqlDumpFile) { if ($this->emptySqlDumpFile) {
unlink($this->emptySqlDumpFile); unlink($this->emptySqlDumpFile);
} }

View File

@ -4,25 +4,17 @@
namespace Tests\Icinga\Web\Form\Element; namespace Tests\Icinga\Web\Form\Element;
use \DateTimeZone;
use Icinga\Test\BaseTestCase; use Icinga\Test\BaseTestCase;
use Icinga\Util\DateTimeFactory;
use Icinga\Web\Form\Element\DateTimePicker; use Icinga\Web\Form\Element\DateTimePicker;
class DateTimeTest extends BaseTestCase class DateTimePickerTest extends BaseTestCase
{ {
/** /**
* Test that DateTimePicker::isValid() returns false if the input is not valid in terms of being a date/time string * Test that DateTimePicker::isValid() returns false if the input is not valid in terms of being a date/time string
* or a timestamp * or a timestamp
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/ */
public function testValidateInvalidInput() public function testValidateInvalidInput()
{ {
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
$dt = new DateTimePicker( $dt = new DateTimePicker(
'foo', 'foo',
array( array(
@ -58,15 +50,9 @@ class DateTimeTest extends BaseTestCase
/** /**
* Test that DateTimePicker::isValid() returns true if the input is valid in terms of being a date/time string * Test that DateTimePicker::isValid() returns true if the input is valid in terms of being a date/time string
* or a timestamp * or a timestamp
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/ */
public function testValidateValidInput() public function testValidateValidInput()
{ {
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
$dt = new DateTimePicker( $dt = new DateTimePicker(
'foo', 'foo',
array( array(
@ -97,15 +83,9 @@ class DateTimeTest extends BaseTestCase
/** /**
* Test that DateTimePicker::getValue() returns a timestamp after a successful call to isValid * Test that DateTimePicker::getValue() returns a timestamp after a successful call to isValid
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/ */
public function testGetValueReturnsUnixTimestampAfterSuccessfulIsValidCall() public function testGetValueReturnsUnixTimestampAfterSuccessfulIsValidCall()
{ {
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('UTC')));
$dt = new DateTimePicker( $dt = new DateTimePicker(
'foo', 'foo',
array( array(
@ -122,33 +102,4 @@ class DateTimeTest extends BaseTestCase
'getValue did not return the correct Unix timestamp according to the given date/time string' 'getValue did not return the correct Unix timestamp according to the given date/time string'
); );
} }
/**
* Test that DateTimePicker::getValue() returns a timestamp respecting
* the given non-UTC time zone after a successful call to isValid
*
* Utilizes singleton DateTimeFactory
*
* @backupStaticAttributes enabled
*/
public function testGetValueIsTimeZoneAware()
{
DateTimeFactory::setConfig(array('timezone' => new DateTimeZone('Europe/Berlin')));
$dt = new DateTimePicker(
'foo',
array(
'patterns' => array(
'd.m.Y H:i:s'
)
)
);
$dt->isValid('12.07.2013 08:03:43');
$this->assertEquals(
1373609023,
$dt->getValue(),
'getValue did not return the correct Unix timestamp according to the given date/time string and time zone'
);
}
} }

View File

@ -49,13 +49,13 @@ class ObjectHookImplementation
class HookTest extends BaseTestCase class HookTest extends BaseTestCase
{ {
protected function setUp() public function setUp()
{ {
parent::setUp(); parent::setUp();
Hook::clean(); Hook::clean();
} }
protected function tearDown() public function tearDown()
{ {
parent::tearDown(); parent::tearDown();
Hook::clean(); Hook::clean();

View File

@ -21,9 +21,10 @@ class NotificationTest extends BaseTestCase
*/ */
private $loggerPath = null; private $loggerPath = null;
protected function setUp() public function setUp()
{ {
Zend_Session::$_unitTestEnabled = true; Zend_Session::$_unitTestEnabled = true;
parent::setUp();
$this->loggerPath = "/tmp/icinga2-web-notify-test"; $this->loggerPath = "/tmp/icinga2-web-notify-test";
$this->dropLog(); $this->dropLog();

View File

@ -18,8 +18,9 @@ class QueryAdapterTest extends BaseTestCase
private $resourceConfig; private $resourceConfig;
protected function setUp() public function setUp()
{ {
parent::setUp();
$this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH; $this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH;
if (!file_exists($this->cacheDir)) { if (!file_exists($this->cacheDir)) {

View File

@ -65,8 +65,9 @@ class SlidingwithborderTest extends BaseTestCase
private $resourceConfig; private $resourceConfig;
protected function setUp() public function setUp()
{ {
parent::setUp();
$this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH; $this->cacheDir = '/tmp'. Reader::STATUSDAT_DEFAULT_CACHE_PATH;
if (!file_exists($this->cacheDir)) { if (!file_exists($this->cacheDir)) {