Commit 01c3f715 authored by Ivan Chepurnyi's avatar Ivan Chepurnyi

! closes feature #56 "Set mock to Magento factories"

! closes feature #55 "Create mock by class alias"
parent d6d016a1
...@@ -32,6 +32,9 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -32,6 +32,9 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
// Admin store code // Admin store code
const ADMIN_STORE_CODE = 'admin'; const ADMIN_STORE_CODE = 'admin';
const REGISTRY_PATH_LAYOUT_SINGLETON = '_singleton/core/layout';
const XML_PATH_LAYOUT_MODEL_FOR_TEST = 'phpunit/suite/layout/model';
/** /**
* Old configuration model to be returned back * Old configuration model to be returned back
* after unit tests are finished * after unit tests are finished
...@@ -122,8 +125,15 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -122,8 +125,15 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
*/ */
public function initTest() public function initTest()
{ {
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
// If garbage collector is not enabled,
// we enable it for tests
if (!gc_enabled()) {
gc_enable();
}
}
$this->_config = Mage::getConfig(); $this->_config = Mage::getConfig();
$this->_config->setOptions($options);
$this->_initBaseConfig(); $this->_initBaseConfig();
$this->_initCache(); $this->_initCache();
...@@ -152,6 +162,12 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App ...@@ -152,6 +162,12 @@ class EcomDev_PHPUnit_Model_App extends Mage_Core_Model_App
Mage_Core_Model_Resource_Setup::applyAllDataUpdates(); Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
} }
$layoutModel = Mage::getModel(
$this->getConfig()->getNode(self::XML_PATH_LAYOUT_MODEL_FOR_TEST)
);
Mage::register(self::REGISTRY_PATH_LAYOUT_SINGLETON, $layoutModel, true);
return $this; return $this;
} }
......
...@@ -31,6 +31,13 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config ...@@ -31,6 +31,13 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
*/ */
protected $_scopeSnapshot = null; protected $_scopeSnapshot = null;
/**
* List of replaced instance creation
*
* @return array
*/
protected $_replaceInstanceCreation = array();
/** /**
* Load config data from DB * Load config data from DB
* *
...@@ -47,6 +54,62 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config ...@@ -47,6 +54,62 @@ class EcomDev_PHPUnit_Model_Config extends Mage_Core_Model_Config
return $this; return $this;
} }
/**
* Replaces creation of some instance by mock object
*
*
* @param string $type
* @param string $classAlias
* @param PHPUnit_Framework_MockObject_MockObject|PHPUnit_Framework_MockObject_MockBuilder $mock
* @return EcomDev_PHPUnit_Model_Config
*/
public function replaceInstanceCreation($type, $classAlias, $mock)
{
$this->_replaceInstanceCreation[$type][$classAlias] = $mock;
return $this;
}
/**
* Flushes instance creation instruction list
*
* @return EcomDev_PHPUnit_Model_Config
*/
public function flushReplaceInstanceCreation()
{
$this->_replaceInstanceCreation = array();
return $this;
}
/**
* Overriden for test case model instance creation mocking
*
* (non-PHPdoc)
* @see Mage_Core_Model_Config::getModelInstance()
*/
public function getModelInstance($modelClass='', $constructArguments=array())
{
if (!isset($this->_replaceInstanceCreation['model'][$modelClass])) {
return parent::getModelInstance($modelClass='', $constructArguments=array());
}
return $this->_replaceInstanceCreation['model'][$modelClass];
}
/**
* Overriden for test case model instance creation mocking
*
* (non-PHPdoc)
* @see Mage_Core_Model_Config::getModelInstance()
*/
public function getResourceModelInstance($modelClass='', $constructArguments=array())
{
if (!isset($this->_replaceInstanceCreation['resource_model'][$modelClass])) {
return parent::getResourceModelInstance($modelClass='', $constructArguments=array());
}
return $this->_replaceInstanceCreation['resource_model'][$modelClass];
}
/** /**
* Loads scope snapshot * Loads scope snapshot
* *
......
<?php
// Loading Spyc yaml parser,
// becuase Symfony component is not working propertly with nested
require_once 'Spyc/spyc.php';
class EcomDev_PHPUnit_Model_Expectation
implements EcomDev_PHPUnit_Model_Expectation_Interface
{
/**
* List of created data object ids by path format
*
* @var array
*/
protected $_dataObjectIds = array();
/**
* Loaded data from Yaml files
*
* @var Varien_Object
*/
protected $_loadedData = null;
/**
* Data object used for managing
* expectation data
*
* @var string
*/
protected $_dataObjectClassAlias = 'ecomdev_phpunit/expectation_object';
/**
* Returns class alias for fixture data object
*
* @return string
*/
public function getDataObjectClassAlias()
{
return $this->_dataObjectClassAlias;
}
/**
* Retrieves data object for a particular path format
*
* @see EcomDev_PHPUnit_Model_Expectation_Interface::getDataObject()
*/
public function getDataObject($pathFormat = null, $args = array())
{
if ($pathFormat === null) {
return $this->_loadedData;
}
$argsHash = $pathFormat . '_' . md5(serialize($args));
// Check already created objects by path
if (!isset($this->_dataObjectIds[$argsHash])) {
if ($args) {
array_unshift($args, $pathFormat);
$dataPath = call_user_func_array('sprintf', $args);
} else {
$dataPath = $pathFormat;
}
$data = $this->_loadedData->getData($dataPath);
if (!is_array($data)) {
throw new InvalidArgumentException(
'Argument values for specifying special scope of expectations should be presented '
. ' in expectation file and should be an associative list (path: "' . $dataPath . '")'
);
}
$this->_dataObjectIds[$argsHash] = Mage::objects()->save(
Mage::getModel($this->getDataObjectClassAlias(), $data)
);
}
return Mage::objects($this->_dataObjectIds[$argsHash]);
}
/**
* Applies loaded data
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::apply()
*/
public function apply()
{
// For now it does nothing :(
return $this;
}
/**
* Removes objects created in object cache
* Clears loaded data property
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::discard()
*/
public function discard()
{
foreach ($this->_dataObjectIds as $objectId) {
Mage::objects()->delete($objectId);
}
$this->_dataObjectIds = array();
$this->_loadedData = null;
return $this;
}
/**
* Check that expectations is loaded
*
* @return boolean
*/
public function isLoaded()
{
return $this->_loadedData !== null;
}
/**
* Loads expected data from test case annotations
*
* @see EcomDev_PHPUnit_Model_Test_Loadable_Interface::loadByTestCase()
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase)
{
$expectations = $testCase->getAnnotationByName('loadExpectation');
if (!$expectations) {
$expectations[] = null;
}
$expectationData = array();
foreach ($expectations as $expectation) {
if (empty($expectation)) {
$expectation = null;
}
$expectationFile = $testCase->getYamlFilePath('expectations', $expectation);
if (!$expectationFile) {
$text = 'There was no expectation defined for current test case';
if ($expectation) {
$text = sprintf('Cannot load expectation %s', $expectation);
}
throw new RuntimeException($text);
}
$expectationData = array_merge_recursive(
$expectationData, Spyc::YAMLLoad($expectationFile)
);
}
$this->_loadedData = new Varien_Object($expectationData);
return $this;
}
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for fixture model
* Can be used for creation of
* absolutely different implementation of fixture,
* then current one.
*
*/
interface EcomDev_PHPUnit_Model_Expectation_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Returns data object with expectations
*
* @param string $pathFormat
* @param array $args arguments for format function
* @return EcomDev_PHPUnit_Model_Expectation_Object
*/
public function getDataObject($pathFormat = null, $args = array());
/**
* Check is expectation loaded
*
* @return boolean
*/
public function isLoaded();
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Expectation data object used for retrieving of data from expectations array
* Created to make possible iteration of expected data,
* for instance if you have list of orders
*
*/
class EcomDev_PHPUnit_Model_Expectation_Object
extends Varien_Object
implements Iterator
{
protected $_createdObjectIds = array();
/**
* Current key in iterator
*
* @var array
*/
protected $_iterationKeys = array();
/**
* If current element is an array,
* then it will be automatically wrapped by
* the same class instance as this one
*
* @see Iterator::current()
* @return null|int|string|boolean|decimal|EcomDev_PHPUnit_Model_Expectation_Object
*/
public function current()
{
if ($this->key() === null) {
return null;
}
$current = $this->_data[$this->key()];
if (is_array($current)) {
$newObject = new self($current);
$this->_createdObjectIds = Mage::objects()
->save($current);
return $newObject;
}
return $current;
}
/* (non-PHPdoc)
* @see Iterator::key()
*/
public function key()
{
return current($this->_iterationKeys);
}
/* (non-PHPdoc)
* @see Iterator::next()
*/
public function next()
{
next($this->_iterationKeys);
}
/* (non-PHPdoc)
* @see Iterator::rewind()
*/
public function rewind()
{
$this->_iterationKeys = $this->keys();
}
/* (non-PHPdoc)
* @see Iterator::valid()
*/
public function valid()
{
return key($this->_iterationKeys) !== null;
}
/**
* Object destructor removes
* created objects from object pool
*
*
*/
public function __destruct()
{
if (!empty($this->_createdObjectIds)) {
foreach ($this->_createdObjectIds as $objectId) {
Mage::objects()->delete($objectId);
}
}
}
/**
* Returns data array keys
*
* @return array
*/
public function keys()
{
return array_keys($this->_data);
}
/**
* Returns data array values
*
* @return array
*/
public function values()
{
return array_values($this->_data);
}
}
...@@ -26,7 +26,9 @@ require_once 'Spyc/spyc.php'; ...@@ -26,7 +26,9 @@ require_once 'Spyc/spyc.php';
* Created for operations with different fixture types * Created for operations with different fixture types
* *
*/ */
class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract class EcomDev_PHPUnit_Model_Fixture
extends Mage_Core_Model_Abstract
implements EcomDev_PHPUnit_Model_Fixture_Interface
{ {
// Configuration path for eav loaders // Configuration path for eav loaders
const XML_PATH_FIXTURE_EAV_LOADERS = 'phpunit/suite/fixture/eav'; const XML_PATH_FIXTURE_EAV_LOADERS = 'phpunit/suite/fixture/eav';
...@@ -114,6 +116,36 @@ class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract ...@@ -114,6 +116,36 @@ class EcomDev_PHPUnit_Model_Fixture extends Mage_Core_Model_Abstract
return $this; return $this;
} }
/**
* Loads fixture from test case annotations
*
* @param EcomDev_PHPUnit_Test_Case $testCase
* @return EcomDev_PHPUnit_Model_Fixture
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase)
{
$fixtures = $testCase->getAnnotationByName(
'loadFixture',
array('class', 'method')
);
foreach ($fixtures as $fixture) {
if (empty($fixture)) {
$fixture = null;
}
$filePath = $testCase->getYamlFilePath('fixtures', $fixture);
if (!$filePath) {
throw new RuntimeException('Unable to load fixture for test');
}
$this->loadYaml($filePath);
}
return $this;
}
/** /**
* Load YAML file * Load YAML file
* *
......
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for fixture model
* Can be used for creation of
* absolutely different implementation of fixture,
* then current one.
*
*/
interface EcomDev_PHPUnit_Model_Fixture_Interface extends EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Sets fixture options
*
* @param array $options
* @return EcomDev_PHPUnit_Model_Fixture_Interface
*/
public function setOptions(array $options);
}
\ No newline at end of file
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Layout model that adds additional functionality
* for testing the layout itself
*
*/
class EcomDev_PHPUnit_Model_Layout extends Mage_Core_Model_Layout
{
/**
* List of replaced blocks creation
*
* @return array
*/
protected $_replaceBlockCreation = array();
/**
* Replaces creation of some block by mock object
*
* @param string $classAlias
* @param PHPUnit_Framework_MockObject_MockObject|PHPUnit_Framework_MockObject_MockBuilder $mock
* @return EcomDev_PHPUnit_Model_Layout
*/
public function replaceBlockCreation($classAlias, $mock)
{
$this->_replaceBlockCreation[$classAlias] = $mock;
return $this;
}
/**
* Flushes instance creation instruction list
*
* @return EcomDev_PHPUnit_Model_Layout
*/
public function flushReplaceBlockCreation()
{
$this->_replaceBlockCreation = array();
return $this;
}
/**
* Overriden for possibility of replacing a block by mock object
* (non-PHPdoc)
* @see Mage_Core_Model_Layout::_getBlockInstance()
*/
protected function _getBlockInstance($block, array $attributes=array())
{
if (!isset($this->_replaceBlockCreation[$block])) {
return parent::_getBlockInstance($block, $attributes);
}
return $this->_replaceBlockCreation[$block];
}
/**
* Resets layout instance properties
*
* @return EcomDev_PHPUnit_Model_Layout
*/
public function reset()
{
$this->setXml(simplexml_load_string('<layout/>', $this->_elementClass));
$this->_update = Mage::getModel('core/layout_update');
$this->_area = null;
$this->_helpers = array();
$this->_directOutput = false;
$this->_output = array();
foreach ($this->_blocks as $block) {
// Remove references between blocks
$block->setParentBlock(null);
$block->setMessageBlock(null);
$block->unsetChildren();
}
$this->_blocks = array();
$this->flushReplaceBlockCreation();
return $this;
}
}
<?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
/**
* Interface for loadable test environment data
*
*/
interface EcomDev_PHPUnit_Model_Test_Loadable_Interface
{
/**
* Loads external data by test case instance
*
* @param EcomDev_PHPUnit_Test_Case $testCase
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function loadByTestCase(EcomDev_PHPUnit_Test_Case $testCase);
/**
* Applies external data
*
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function apply();
/**
* Reverts applied data
*
* @return EcomDev_PHPUnit_Model_Test_Loadable_Interface
*/
public function discard();
}
...@@ -27,10 +27,23 @@ require_once 'Spyc/spyc.php'; ...@@ -27,10 +27,23 @@ require_once 'Spyc/spyc.php';
*/ */
abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
{ {
const XML_PATH_DEFAULT_FIXTURE_MODEL = 'phpunit/suite/fixture/model';
const XML_PATH_DEFAULT_EXPECTATION_MODEL = 'phpunit/suite/expectatio/model';
/**
* List of system registry values replaced by test case
*
* @var array
*/
protected $_replacedRegistry = array();
/** /**
* The expectations for current test are loaded here * The expectations for current test are loaded here
* *
* @var Varien_Object|null * @var Varien_Object|null
* @deprecated since 0.2.0
*/ */
protected $_expectations = null; protected $_expectations = null;
...@@ -42,93 +55,402 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -42,93 +55,402 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
protected $_originalStore = null; protected $_originalStore = null;
/**
* Retrieves annotation by its name from different sources (class, method)
*
*
* @param string $name
* @param array|string $sources
* @return array
*/
public function getAnnotationByName($name, $sources = 'method')
{
if (is_string($sources)) {
$source = array($sources);
}
$allAnnotations = $this->getAnnotations();
$annotation = array();
// Walkthrough sources for annotation retrieval
foreach ($sources as $source) {
if (isset($allAnnotations[$source][$name])) {
$annotation = array_merge(
$allAnnotations[$source][$name],
$annotation
);
}
}
return $annotation;
}
/** /**
* Loads expectations for current test case * Loads expectations for current test case
* *
* @throws RuntimeException if no expectation was found * @throws RuntimeException if no expectation was found
* @return Varien_Object * @return Varien_Object
* @deprecated since 0.2.0, use self::expected() instead.
*/ */
protected function _getExpectations() protected function _getExpectations()
{ {
if ($this->_expectations === null) { $arguments = func_get_args();
$annotations = $this->getAnnotations();
if (isset($annotations['method']['loadExpectation'])) { return $this->expected($arguments);
// Load expectation by annotations }
$expectations = array();
foreach ($annotations['method']['loadExpectation'] as $expectation) { /**
if (empty($expectation)) { * Replaces Magento resource by mock object
$expectation = null; *
} *
* @param string $type
$expectationFile = $this->_getYamlFilePath('expectations', $expectation); * @param string $classAlias
if ($expectationFile) { * @param PHPUnit_Framework_MockObject_MockObject|PHPUnit_Framework_MockObject_MockBuilder $mock
$expectations = array_merge_recursive( * @return EcomDev_PHPUnit_Test_Case
$expectations, Spyc::YAMLLoad($expectationFile) */
protected function replaceByMock($type, $classAlias, $mock)
{
if ($mock instanceof PHPUnit_Framework_MockObject_MockBuilder) {
$mock = $mock->getMock();
} elseif (!$mock instanceof PHPUnit_Framework_MockObject_MockObject) {
throw PHPUnit_Util_InvalidArgumentHelper::factory(
1, 'PHPUnit_Framework_MockObject_MockObject'
); );
} else {
$text = 'There was no expectation defined for current test case';
if ($expectation) {
$text = sprintf('Cannot load expectation %s', $expectation);
} }
throw new RuntimeException($test);
if ($type == 'helper' && strpos($classAlias, '/') === false) {
$classAlias .= '/data';
} }
if (in_array($type, array('model', 'resource_model'))) {
Mage::getConfig()->replaceInstanceCreation($type, $classAlias, $mock);
$type = str_replace('model', 'singleton', $type);
} elseif ($type == 'block') {
Mage::app()->getLayout()->replaceBlockCreation($classAlias, $mock);
} }
} else {
// Load expectations by test name if (in_array($type, array('singleton', 'resource_singleton', 'helper'))) {
$expectationFile = $this->_getYamlFilePath('expectations'); $registryPath = '_' . $type . '/' . $classAlias;
if ($expectationFile) { $this->replaceRegistry($registryPath, $mock);
$expectations = Spyc::YAMLLoad($expectationFile);
} else {
throw new RuntimeException('There was no expectation defined for current test case');
} }
return $this;
}
/**
* Replaces value in Magento system registry
*
* @param string $key
* @param mixed $value
*/
protected function replaceRegistry($key, $value)
{
$oldValue = Mage::registry($key);
Mage::register($key, $value, true);
$this->_replacedRegistry[$key] = $oldValue;
return $this;
} }
$this->_expectations = new Varien_Object($expectations); /**
* Shortcut for expectation data object retrieval
* Can be called with arguments array or in usual method
*
* @param string|array $pathFormat
* @param mixed $arg1
* @param mixed $arg2 ...
* @return Varien_Object
*/
protected function expected($firstArgument = null)
{
if (!$this->getExpectation()->isLoaded()) {
$this->getExpectation()->loadByTestCase($this);
$this->getExpectation()->apply();
} }
if (!is_array($firstArgument)) {
$arguments = func_get_args(); $arguments = func_get_args();
} else {
$arguments = $firstArgument;
}
$pathFormat = null;
if ($arguments) { if ($arguments) {
if (count($arguments) > 1) { $pathFormat = array_shift($arguments);
$dataKey = call_user_func_array('sprintf', $arguments); }
return $this->getExpectation()
->getDataObject($pathFormat, $arguments);
}
/**
* Retrieve mock builder for grouped class alias
*
* @param string $type block|model|helper
* @param string $classAlias
* @return PHPUnit_Framework_MockObject_MockBuilder
*/
public function getGroupedClassMockBuilder($type, $classAlias)
{
$className = Mage::getConfig()->getGroupedClassName($type, $classAlias);
return $this->getMockBuilder($className);
}
/**
* Retrieves a mock builder for a block class alias
*
* @param string $classAlias
* @return PHPUnit_Framework_MockObject_MockBuilder
*/
public function getBlockMockBuilder($classAlias)
{
return $this->getGroupedClassMockBuilder('block', $classAlias);
}
/**
* Retrieves a mock builder for a model class alias
*
* @param string $classAlias
* @return PHPUnit_Framework_MockObject_MockBuilder
*/
public function getModelMockBuilder($classAlias)
{
return $this->getGroupedClassMockBuilder('model', $classAlias);
}
/**
* Retrieves a mock builder for a helper class alias
*
* @param string $classAlias
* @return PHPUnit_Framework_MockObject_MockBuilder
*/
public function getHelperMockBuilder($classAlias)
{
return $this->getGroupedClassMockBuilder('helper', $classAlias);
}
/**
* Retrieves a mock object for the specified model class alias.
*
* @param string $classAlias
* @param array $methods
* @param boolean $isAbstract
* @param array $constructorArguments
* @param string $mockClassAlias
* @param boolean $callOriginalConstructor
* @param boolean $callOriginalClone
* @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getModelMock($classAlias, $methods = array(), $isAbstract = false,
array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('model', $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
}
/**
* Retrieves a mock object for the specified helper class alias.
*
* @param string $classAlias
* @param array $methods
* @param boolean $isAbstract
* @param array $constructorArguments
* @param string $mockClassAlias
* @param boolean $callOriginalConstructor
* @param boolean $callOriginalClone
* @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getHelperMock($classAlias, $methods = array(), $isAbstract = false,
array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('helper', $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
}
/**
* Retrieves a mock object for the specified helper class alias.
*
* @param string $classAlias
* @param array $methods
* @param boolean $isAbstract
* @param array $constructorArguments
* @param string $mockClassAlias
* @param boolean $callOriginalConstructor
* @param boolean $callOriginalClone
* @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getBlockMock($classAlias, $methods = array(), $isAbstract = false,
array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
return $this->getGroupedClassMock('block', $methods, $isAbstract,
$constructorArguments, $mockClassAlias,
$callOriginalConstructor, $callOriginalClone,
$callAutoload);
}
/**
* Returns class name by grouped class alias
*
* @param string $type block/model/helper/resource_model
* @param string $classAlias
*/
protected function getGroupedClassName($type, $classAlias)
{
if ($type === 'resource_model') {
return Mage::getConfig()->getResourceModelClassName($classAlias);
}
return Mage::getConfig()->getGroupedClassName($type, $classAlias);
}
/**
* Retrieves a mock object for the specified grouped class alias.
*
* @param string $type
* @param string $classAlias
* @param array $methods
* @param boolean $isAbstract
* @param array $constructorArguments
* @param string $mockClassAlias
* @param boolean $callOriginalConstructor
* @param boolean $callOriginalClone
* @param boolean $callAutoload
* @return PHPUnit_Framework_MockObject_MockObject
*/
public function getGroupedClassMock($type, $classAlias, $methods = array(), $isAbstract = false,
array $constructorArguments = array(),
$mockClassAlias = '', $callOriginalConstructor = true,
$callOriginalClone = true, $callAutoload = true)
{
if (!empty($mockClassAlias)) {
} else { } else {
$dataKey = array_shift($arguments); $mockClassName = '';
} }
$dataPart = $this->_expectations->getData($dataKey); $mockBuilder = $this->getGroupedClassMockBuilder($type, $classAlias);
if (!is_array($dataPart)) {
throw new InvalidArgumentException( if ($callOriginalConstructor === false) {
'Argument values for specifying special scope of expectations should be presented ' $mockBuilder->disableOriginalConstructor();
. ' in expectation file and should be an associative list (dataKey: "' . $dataKey . '")' }
);
if ($callOriginalClone === false) {
$mockBuilder->disableOriginalClone();
} }
return new Varien_Object($dataPart); if ($callAutoload === false) {
$mockBuilder->disableAutoload();
} }
return $this->_expectations; $mockBuilder->setMethods($methods);
$mockBuilder->setConstructorArgs($arguments);
$mockBuilder->setMockClassName($mockClassName);
if ($isAbstract) {
return $mockBuilder->getMockForAbstractClass();
} }
return $mockBuilder->getMock();
}
/** /**
* Retrieves fixture model singleton * Retrieves fixture model singleton
* *
* @return EcomDev_PHPUnit_Model_Fixture * @return EcomDev_PHPUnit_Model_Fixture
* @deprecated since 0.2.0 use getFixture() method instead
*/ */
protected function _getFixture() protected function _getFixture()
{ {
return Mage::getSingleton('ecomdev_phpunit/fixture'); return $this->getFixture();
} }
/** /**
* Loads YAML file from directory inside of the unit test class * Retrieves fixture model singleton
* Enter description here ... *
* @return EcomDev_PHPUnit_Model_Fixture
*/
protected function getFixture()
{
return Mage::getSingleton($this->getLoadableClassAlias(
'fixture',
self::XML_PATH_DEFAULT_FIXTURE_MODEL
));;
}
/**
* Returns expectation model singleton
*
* @return EcomDev_PHPUnit_Model_Expectation
*/
protected function getExpectation()
{
return Mage::getSingleton($this->getLoadableClassAlias(
'expectation',
self::XML_PATH_DEFAULT_EXPECTATION_MODEL
));
}
/**
* Retrieves loadable class alias from annotation or configuration node
* E.g. class alias for fixture model can be specified via @fixtureModel annotation
*
* @param string $type
* @param string $configPath
*/
protected function getLoadableClassAlias($type, $configPath)
{
$annotationValue = $this->getAnnotationByName($type .'Model' , 'class');
if (current($annotationValue)) {
$classAlias = current($annotationValue);
} else {
$classAlias = Mage::getConfig()->getNode($configPath);
}
return $classAlias;
}
/**
* Protected wrapper for _getYamlFilePath method. Backward campatibility.
*
* @see EcomDev_PHPUnit_Test_Case::getYamlFilePath()
* *
* @param string $type type of YAML data (fixtures,expectations,dataproviders) * @param string $type type of YAML data (fixtures,expectations,dataproviders)
* @param string|null $name the file name for loading, if equals to null, * @param string|null $name the file name for loading, if equals to null,
* the current test name will be used * the current test name will be used
* @return string|boolean * @return string|boolean
* @deprecated since 0.2.0
*/ */
protected function _getYamlFilePath($type, $name = null) protected function _getYamlFilePath($type, $name = null)
{
return $this->getYamlFilePath($type, $name);
}
/**
* Loads YAML file from directory inside of the unit test class
*
* @param string $type type of YAML data (fixtures,expectations,dataproviders)
* @param string|null $name the file name for loading, if equals to null,
* the current test name will be used
* @return string|boolean
*/
public function getYamlFilePath($type, $name = null)
{ {
if ($name === null) { if ($name === null) {
$name = $this->getName(false); $name = $this->getName(false);
...@@ -161,24 +483,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -161,24 +483,11 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
*/ */
protected function setUp() protected function setUp()
{ {
$annotations = $this->getAnnotations(); $this->getFixture()->loadByTestCase($this);
if (isset($annotations['method']['loadFixture'])) {
foreach ($annotations['method']['loadFixture'] as $fixture) {
if (empty($fixture)) {
$fixture = null;
}
$filePath = $this->_getYamlFilePath('fixtures', $fixture);
if (!$filePath) {
throw new RuntimeException('Unable to load fixture for test');
}
$this->_getFixture()->loadYaml($filePath); $annotations = $this->getAnnotations();
} $this->getFixture()->setOptions($annotations['method']);
} $this->getFixture()->apply();
// Pass methods for
$this->_getFixture()->setOptions($annotations['method']);
$this->_getFixture()->apply();
parent::setUp(); parent::setUp();
} }
...@@ -186,12 +495,13 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -186,12 +495,13 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
* Implements default data provider functionality, * Implements default data provider functionality,
* returns array data loaded from Yaml file with the same name as test method * returns array data loaded from Yaml file with the same name as test method
* *
* @param string $testName
* @return array * @return array
*/ */
public function dataProvider($testName) public function dataProvider($testName)
{ {
$this->setName($testName); $this->setName($testName);
$filePath = $this->_getYamlFilePath('providers'); $filePath = $this->getYamlFilePath('providers');
$this->setName(null); $this->setName(null);
if (!$filePath) { if (!$filePath) {
...@@ -231,8 +541,19 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase ...@@ -231,8 +541,19 @@ abstract class EcomDev_PHPUnit_Test_Case extends PHPUnit_Framework_TestCase
$this->_originalStore = null; $this->_originalStore = null;
} }
$this->_expectations = null; // Clear expectation values if ($this->getExpectation()->isLoaded()) {
$this->_getFixture()->discard(); // Clear applied fixture $this->getExpectation()->discard();
}
Mage::getConfig()->flushReplaceInstanceCreation();
Mage::app()->getLayout()->reset();
foreach ($this->_replacedRegistry as $registryPath => $originalValue) {
Mage::register($registryPath, $originalValue, true);
}
$this->getFixture()->discard(); // Clear applied fixture
parent::tearDown(); parent::tearDown();
} }
......
...@@ -51,9 +51,16 @@ ...@@ -51,9 +51,16 @@
<helpers>Helper</helpers> <helpers>Helper</helpers>
<blocks>Block</blocks> <blocks>Block</blocks>
</groups> </groups>
<!-- Test suite that will be used for creation of each of the tests --> <layout>
<test_suite>EcomDev_PHPUnit_Test_Suite_Group</test_suite> <model>ecomdev_phpunit/layout</model>
</layout>
<expectation>
<!-- Default model for loading of expectations -->
<model>ecomdev_phpunit/expectation</model>
</expectation>
<fixture> <fixture>
<!-- Default model for loading of fixtures -->
<model>ecomdev_phpunit/fixture</model>
<eav> <eav>
<!-- Here goes the list of fixture loaders for EAV <!-- Here goes the list of fixture loaders for EAV
If no fixture loader is specified for entity, then default will be used If no fixture loader is specified for entity, then default will be used
......
<?php <?php
/**
* PHP Unit test suite for Magento
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
*
* @category EcomDev
* @package EcomDev_PHPUnit
* @copyright Copyright (c) 2011 Ecommerce Developers (http://www.ecomdev.org)
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* @author Ivan Chepurnyi <ivan.chepurnyi@ecomdev.org>
*/
class EcomDev_Utils_Reflection class EcomDev_Utils_Reflection
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment