i have code like this:
protected function _checkUserVisibility()
{
try {
if (!$params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
throw new Unitex_Exception('ALARM');
}
}
catch (Exception $e) {
$this->logOut();
throw $e;
}
}
this func caled from another one (and so on).
a a question:
how to get worked unit test for that parts of code?
EDIT1:
firstly taked hehe http://framework.zend.com/manual/1.12/en/zend.test.phpunit.html
than improoved (hope)
test proc is:
class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase {
..........
public function testLoginAction()
{
$request = $this->getRequest();
$request->setMethod('POST')
->setHeader('X_REQUESTED_WITH', 'XMLHttpRequest')
->setPost(array(
'user' => 'test_user',
'password' => 'test_pwd',
));
$filialId = 1;
$stmt1 = Zend_Test_DbStatement::createUpdateStatement();
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->getAdapter()->appendStatementToStack($stmt1);
$stmt1Rows = array(array('IRL_ALIAS' => 'RO_COMMON', 'ISADM' => 'N'));
$stmt1 = Zend_Test_DbStatement::createSelectStatement($stmt1Rows);
$this->getAdapter()->appendStatementToStack($stmt1);
$this->dispatch('/user/login');// <-- crash here
$this->assertController('user');
$this->assertAction('login');
$this->assertNotRedirect();
$this->_getResponseJson();
}
In your unit test definitly you don't want any database interaction. The answer for your question is use stub for db functionality.
Let say that $params is property of SomeClass contains getUsrParametr which for example gets something from database. You're testing _checkUserVisibility method so you don't care about what are happening in SomeClass. That's way you test will look something like that:
class YourClass
{
protected $params;
public function __construct(SomeClass $params)
{
$this->params = $params;
}
public function doSomething()
{
$this->_checkUserVisibility();
}
protected function _checkUserVisibility()
{
try {
if (!$this->params->getUsrParametr(self::ACTIVE_FIF)) { // calling oracle stored proc
throw new Unitex_Exception('ALARM');
}
}
catch (Exception $e) {
$this->logOut();
throw $e;
}
}
}
And the unit test of course the only method you test is the public one, but you cover protected method through testing public one.
public function testDoSomethingAlarm()
{
// set expected exception:
$this->setExpectedException('Unitex_Exception', 'ALARM');
// create the stub
$params = $this->getMock('SomeClass', array('getUsrParametr'));
// and set desired result
$params->expects($this->any())
->method('getUsrParametr')
->will($this->returnValue(false));
$yourClass = new YourClass($params);
$yourClass->doSomething();
}
And the second test which test case if getUsrParametr will returns true:
public function testDoSomethingLogout()
{
// set expected exception:
$this->setExpectedException('SomeOtherException');
// create the stub
$params = $this->getMock('SomeClass', array('getUsrParametr'));
// set throw desired exception to test logout
$params->expects($this->any())
->method('getUsrParametr')
->will($this->throwException('SomeOtherException'));
// now you want create mock instead of real object beacuse you want check if your class will call logout method:
$yourClass = $this->getMockBuilder('YourClass')
->setMethods(array('logOut'))
->setConstructorArgs(array($params))
->getMock();
// now you want ensure that logOut will be called
$yourClass->expects($this->once())
->method('logOut');
// pay attention that you've mocked only logOut method, so doSomething is real one
$yourClass->doSomething();
}
If you're using PHP 5.3.2+ with PHPUnit, you can test your private and protected methods by using reflection to set them to be public prior to running your tests, otherwise you test protected/private methods by properly testing the public methods that use the protected/private methods. Generally speaking the later of the two options is generally how you should do it, but if you want to use reflection, here's a generic example:
protected static function getMethod($name) {
$class = new ReflectionClass('MyClass');
$method = $class->getMethod($name);
$method->setAccessible(true);
return $method;
}
public function testFoo() {
$foo = self::getMethod('foo');
$obj = new MyClass();
$foo->invokeArgs($obj, array(...));
...
}
Related
I try to call a function from a module A to a module B
here is the module A code
namespace A\Epayment\Model;
class Etransactions
{
public function customPayment{
return "test";
}
and module b code
namespace B\Payment\Controller\Index;
class Payment extends \Magento\Framework\App\Action\Action
{
protected $_pageFactory;
protected $_transaction;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory,
\ETransactions\Epayment\Model\Etransactions $transaction
)
{
$this->_pageFactory = $pageFactory;
$this->_transaction = $transaction;
parent::__construct($context);
}
public function execute()
{
echo "Hello World".PHP_EOL;
$foo="a";
echo $foo;
echo $this->_transaction->customPayment();
//echo $this->customPayment();
echo $foo;
exit;
}
}
this code return the "hello world", the first $foo, not the second and doesn't display any error
can someone explain me where is my error ?
EDIT: i didn't change anything but it works fine now.
thanks for the answers anyway
The object you want create the path your are injecting is incorrect.
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory,
\A\Epayment\Model\Etransactions $transaction // changes are here
)
{
$this->_pageFactory = $pageFactory;
$this->_transaction = $transaction;
parent::__construct($context);
}
Kindly use exception handling.
try{
$this->_transaction->customPayment();
}catch(Exception $e){
//log your exception here.
}
In Magento, Helper classes are available to use anywhere (Block, Controller, Model, Observer, View). So you should create a method in helper class and call it anywhere by the following way.
Declar the helper class and method: ModuleA\Epayment\Helper\Data.
<?php
namespace ModuleA\Epayment\Helper;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
public function yourHelperMethod()
{
# code...
}
}
Call the method:
$helper = $this->_objectManager->create(ModuleA\Epayment\Helper\Data::class);
$helper->yourHelperMethod();
Note: If the object manager is not injected in your class. Please follow the steps below:
1) declare private property:
private $_objectManager;
2) inject in the constructor to initialize:
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectmanager
) {
$this->_objectManager = $objectmanager;
}
3) use in some method:
public function someMethod() {
$helper = $this->_objectManager->create(ModuleA\Epayment\Helper\Data::class);
$helper->yourHelperMethod();
}
I am new to kohana framework. I need to implement rest api for my application.
I have downloded rest api from https://github.com/SupersonicAds/kohana-restful-api and placed in my localhost. Under modules. now the file structre is
I have enabled module in bootstrap.php as
Kohana::modules(array(
'auth' => MODPATH.'auth', // Basic authentication
'rest' => MODPATH.'rest', // Basic Rest example
// 'cache' => MODPATH.'cache', // Caching with multiple backends
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
'database' => MODPATH.'database', // Database access
// 'image' => MODPATH.'image', // Image manipulation
// 'minion' => MODPATH.'minion', // CLI Tasks
'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'unittest' => MODPATH.'unittest', // Unit testing
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
));
i have created a controller by extending "Controller_Rest" Now according to wiki i should be able to access "$this->_user, $this->_auth_type and $this->_auth_source" variables but in my case its not happening what i am doing wrong?
And i checked in console network it always showing status as "401 Unauthorised"
For using Authorization,you need to extend Kohana_RestUser Class
The module you are using comes with an abstract Kohana_RestUser class, which you must extend in your app. The only function that requires implementation is the protected function _find(). The function's implementation is expected to load any user related data, based on an API key.
I will explain you with an example
<?php
// Model/RestUser.php
class RestUser extends Kohana_RestUser {
protected $user='';
protected function _find()
{
//generally these are stored in databases
$api_keys=array('abc','123','testkey');
$users['abc']['name']='Harold Finch';
$users['abc']['roles']=array('admin','login');
$users['123']['name']='John Reese';
$users['123']['roles']=array('login');
$users['testkey']['name']='Fusco';
$users['testkey']['roles']=array('login');
foreach ($api_keys as $key => $value) {
if($value==$this->_api_key){
//the key is validated which is authorized key
$this->_id = $key;//if this not null then controller thinks it is validated
//$this->_id must be set if key is valid.
//setting name
$this->user = $users[$value];
$this->_roles = $users[$value]['roles'];
break;
}
}
}//end of _find
public function get_user()
{
return $this->name;
}
}//end of RestUser
Now Test Controller
<?php defined('SYSPATH') or die('No direct script access.');
//Controller/Test.php
class Controller_Test extends Controller_Rest
{
protected $_rest;
// saying the user must pass an API key.It is set according to the your requirement
protected $_auth_type = RestUser::AUTH_TYPE_APIKEY;
// saying the authorization data is expected to be found in the request's query parameters.
protected $_auth_source = RestUser::AUTH_SOURCE_GET;//depends on requirement/coding style
//note $this->_user is current Instance of RestUser Class
public function before()
{
parent::before();
//An extension of the base model class with user and ACL integration.
$this->_rest = Model_RestAPI::factory('RestUserData', $this->_user);
}
//Get API Request
public function action_index()
{
try
{
$user = $this->_user->get_name();
if ($user)
{
$this->rest_output( array(
'user'=>$user,
) );
}
else
{
return array(
'error'
);
}
}
catch (Kohana_HTTP_Exception $khe)
{
$this->_error($khe);
return;
}
catch (Kohana_Exception $e)
{
$this->_error('An internal error has occurred', 500);
throw $e;
}
}
//POST API Request
public function action_create()
{
//logic to create
try
{
//create is a method in RestUserData Model
$this->rest_output( $this->_rest->create( $this->_params ) );
}
catch (Kohana_HTTP_Exception $khe)
{
$this->_error($khe);
return;
}
catch (Kohana_Exception $e)
{
$this->_error('An internal error has occurred', 500);
throw $e;
}
}
//PUT API Request
public function action_update()
{
//logic to create
}
//DELETE API Request
public function action_delete()
{
//logic to create
}
}
Now RestUserData Model
<?php
//Model/RestUserData.php
class Model_RestUserData extends Model_RestAPI {
public function create($params)
{
//logic to store data in db
//You can access $this->_user here
}
}
So index.php/test?apiKey=abc returns
{
"user": {
"name": "Harold Finch",
"roles": [
"admin",
"login"
]
}
}
Note: K in apiKey is Capital/UpperCase
I Hope this Helps
Happy Coding :)
To stay basic I would like to create a bookmark app
I have a simple bookmarklet
javascript:location.href='http://zas.dev/add?url='+encodeURIComponent(location.href)
I created a rest controller
<?php
use zas\Repositories\DbLinkRepository;
class LinksController extends BaseController {
protected $link;
function __construct(DbLinkRepository $link) {
$this->link=$link;
// ...
//$this->beforeFilter('auth.basic', array('except' => array('index', 'show', 'store')));
// ...
}
public function index()
{
//return Redirect::to('home');
}
public function create()
{
}
public function store()
{
return 'hello';
//$this->link->addLink(Input::get('url'));
//return Redirect::to(Input::get('url'));
}
public function show($id)
{
//$url = $this->link->getUrl($id);
//return Redirect::to($url);
}
public function edit($id)
{
}
public function update($id){
}
public function destroy($id){
}
}
in the routes.php, I created a ressource
Route::resource('links','LinksController');
and as I want to redirect /add to the store method I added
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
but it never display the hello message, in place it redirects me to
http://zas.dev/links
I also tried with
return Redirect::route('links.store');
without much success
thanks for your help
Ok I now get what you are trying to do. This will work:
Route::get('add', 'LinksController#store');
Remove:
Route::resource('links','LinksController');
and remove:
Route::get('/add',function(){
return Redirect::action('LinksController#store');
});
Sorry it took so long!
The problem is that once you Redirect::, you loose all the Input values, so you should manually give them to your controller when you do the redirect, like so :
Redirect::route('links.store', ["url" => Input::get("url")]);
Finally add an $url parameter to your store method to receive the value we give it in the previous method, like this :
public function store($url) {
$this->link->addLink($url);
return Redirect::to($url);
}
I am trying to call model methods from controller. but I am getting Fatal error: Class 'GuestModel' not found in. error
following is the code ::
Controller ::
class GuestController extends Zend_Controller_Action
{
public function indexAction(){
$guestbook = new GuestModel();
$this->view->entries = $guestbook->fetchAll();
}
}
Model::
class GuestModel extends Zend_Db_Table_Abstract
{
public function fetchAll()
{
$resultSet = $this->getDbTable()->fetchAll();
$entries = array();
foreach ($resultSet as $row) {
$entry = new Application_Model_Guestbook();
$entry->setId($row->id)
->setEmail($row->email)
->setComment($row->comment)
->setCreated($row->created);
$entries[] = $entry;
}
return $entries;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Guestbook');
}
return $this->_dbTable;
}
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
}
Zend Framework autoload depends on using the correct directory structure and file naming conventions to find the classes automagically, from the looks of your code my guess would be you're not following it.
I see 2 possible solutions for your problem:
If possible, rename your class to Application_Model_Guestbook, the file to Guestbook.php and make sure to move it to your application/models/ directory. Then you just need to call it in your controller as $guestbook = new Application_Model_Guestbook();. Check this documentation example;
Create your own additional autoloading rules. Check the official documentation regarding Resource Autoloading.
I'm trying to find a way to test a abstract class constant that must exist and match/not match a value. Example:
// to be extended by ExternalSDKClild
abstract class ExternalSDK {
const VERSION = '3.1.1.';
}
class foo extends AController {
public function init() {
if ( ExternalSDK::VERSION !== '3.1.1' ) {
throw new Exception('Wrong ExternalSDK version!');
}
$this->setExternalSDKChild(new ExternalSDKChild());
}
}
Limitations... The framework we use doesn't allow dependency injection in the init() method. (Suggestion to refactor the init() method could be the way to go...)
The unit tests and code coverage I have run, cover all but the Exception. I can't figure out a way to make the ExternalSDK::Version to be different from what it is.
All thoughts welcome
First, refactor the call to new into a separate method.
Second, add a method to acquire the version instead of accessing the constant directly. Class constants in PHP are compiled into the file when parsed and cannot be changed.* Since they are accessed statically, there's no way to override it without swapping in a different class declaration with the same name. The only way to do that using standard PHP is to run the test in a separate process which is very expensive.
class ExternalSDK {
const VERSION = '3.1.1';
public function getVersion() {
return static::VERSION;
}
}
class foo extends AController {
public function init() {
$sdk = $this->createSDK();
if ( $sdk->getVersion() !== '3.1.1' ) {
throw new Exception('Wrong ExternalSDK version!');
}
$this->setExternalSDKChild($sdk);
}
public function createSDK() {
return new ExternalSDKChild();
}
}
And now for the unit test.
class NewerSDK extends ExternalSDK {
const VERSION = '3.1.2';
}
/**
* #expectedException Exception
*/
function testInitFailsWhenVersionIsDifferent() {
$sdk = new NewerSDK();
$foo = $this->getMock('foo', array('createSDK'));
$foo->expects($this->once())
->method('createSDK')
->will($this->returnValue($sdk));
$foo->init();
}
*Runkit provides runkit_constant_redefine() which may work here. You'll need to catch the exception manually instead of using #expectedException so you can reset the constant back to the correct value. Or you can do it in tearDown().
function testInitFailsWhenVersionIsDifferent() {
try {
runkit_constant_redefine('ExternalSDK::VERSION', '3.1.0');
$foo = new foo();
$foo->init();
$failed = true;
}
catch (Exception $e) {
$failed = false;
}
runkit_constant_redefine('ExternalSDK::VERSION', '3.1.1');
if ($failed) {
self::fail('Failed to detect incorrect SDK version.');
}
}