I have an artisan command which gets some options, one of these options is --type=, like below:
protected $signature = 'make:procedure {name} {--type=}';
--type= contains the kind of difference, I want to check this option in the stub because each type has a different namespace which should be used in the stub.
for example, this is my stub:
<?php
namespace DummyNamespace;
class DummyClass
{
//
}
How can I do this, (of course this is an example, I just trying to explain my problem):
<?php
namespace DummyNamespace;
if ($type === 'one') {
echo 'use App\Some\Namespace\One'
}
class DummyClass
{
//
}
It would be highly appreciated if anyone can advise me!😊
your Custom command should derive from GeneratorCommand then you can use abstract Method getStub()
Your Stub File
namespace DummyNamespace;
/**
* Class DummyClass.
*/
class DummyClass
{
}
In Your Command File, you just need to use below code
/**
* Get the stub file for the generator.
*
* #return string
*/
protected function getStub()
{
return app_path('file/path/test.stub');
}
For Explanation Only
In GeneratorCommand class
/**
* Get the stub file for the generator.
*
* #return string
*/
abstract protected function getStub();
/**
* Build the class with the given name.
*
* #param string $name
* #return string
*
* #throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
protected function buildClass($name)
{
$stub = $this->files->get($this->getStub());
return $this->replaceNamespace($stub, $name)->replaceClass($stub, $name);
}
A very simple way to generate files from stub.
In your stub file
namespace {{namespace}};
/**
* Class {{name}}.
*/
class {{name}}
{
}
Somewhere in your command
protected function getStub()
{
return file_get_contents(resource_path('stubs/dummy.stub'));
}
protected function generate($namespace, $name)
{
$template = str_replace(
['{{namespace}}', '{{name}}'],
[$namespace, $name],
$this->getStub()
);
file_put_contents(app_path("Dummies/$name.php"), $template);
}
Is there any option to inform PhpStorm that method which it says that not exist, is beyond his scope and is defined somewhere else ?
In simpler words:
I have method execution:
Db::transactional($this)->transactionalUpdate($result);
I have got method definition also:
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...';
}
Unfortunately PhpStorm doesn't know that execution : ->transactionalUpdate($result); should run public function transactionalUpdate.
Is there any option to write PhpDoc or some other tag to inform it that in case of name refactorization it should change the original function name too ?
P.S. My class structure looks like this:
class Db
{
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
class ApiObject
{
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
}
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
EDIT AFTER ANSWER:
#Nukeface and #Dmitry caused me to come up with the answer on my Question:
Lets see again into my files structure:
class Db
{
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
class ApiObject
{
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
//EDIT//Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
/** #var self $thisObject */
//Line above informs PhpStorm that $thisObject is ApiObject indeed
$thisObject = Db::transactional($this)
$thisObject->transactionalUpdate($result);
}
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
You should make use of Typehints. Updated your code below:
/**
* Class Db
* #package Namespace\To\Db
*/
class Db
{
/**
* #param $object
* #return ApiObject (per your line comment)
*/
public static function transactional($object)
{
return TransactionalProxy::newInstance($object); //3. It returns ApiObject object
}
}
/**
* Class ApiObject
* #package Namespace\To\ApiObject
*/
class ApiObject
{
/**
* #return void (I see no "return" statement)
*/
public function update_record()
{
//1. I am starting from there
$result = new ImportantObjectButNotMuch();
Db::transactional($this)->transactionalUpdate($result); //2. Next i am passing $this to Db class, to transactional method //4. It should run below transactionalUpdate method
}
/**
* #param ImportantObjectButNotMuch $baconWithButter
* #return void
*/
public function transactionalUpdate(ImportantObjectButNotMuch $baconWithButter)
{
echo 'Do a lot of tricks...'; //5. It ends there, it is working but PhpStorm doesn't see it
}
}
You can quickly create basic docblocks and typehints by typing /** then pressing either "enter" or "space". Enter if you want a docblock and space if you want a typehint.
Examples of own code below:
/**
* Class AbstractEventHandler
* #package Hzw\Mvc\Event
*/
abstract class AbstractEventHandler implements EventManagerAwareInterface
{
/**
* #var EventManagerInterface
*/
protected $events;
/**
* #var EntityManager|ObjectManager
*/
protected $entityManager;
/**
* AbstractEvent constructor.
* #param ObjectManager $entityManager
*/
public function __construct(ObjectManager $entityManager)
{
$this->setEntityManager($entityManager);
}
/**
* #param EventManagerInterface $events
*/
public function setEventManager(EventManagerInterface $events)
{
$events->setIdentifiers([
__CLASS__,
get_class($this)
]);
$this->events = $events;
}
/**
* #return EventManagerInterface
*/
public function getEventManager()
{
if (!$this->events) {
$this->setEventManager(new EventManager());
}
return $this->events;
}
/**
* #return ObjectManager|EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* #param ObjectManager|EntityManager $entityManager
* #return AbstractEventHandler
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
return $this;
}
}
In the above example, PhpStorm knows what every function requires and returns. It knows the types and as some "return $this" it knows about the possibility to chain functions.
As an addition, the above code example uses only "docblocks". Below some "inline typehints" from within a function. Especially useful when it's not going to be immediately clear what is going to be returned. That way, again, PhpStorm knows from where to get functions, options, etc. to show you.
/** #var AbstractForm $form */
$form = $this->getFormElementManager()->get($formName, (is_null($formOptions) ? [] : $formOptions));
/** #var Request $request */
$request = $this->getRequest();
As a final hint. If you create a bunch of properties for a class, such as in my example protected $events or protected $entityManager, you can also generate the getters & setters. If your properties contain the docblocks, it will also generate the docblocks for you on these functions.
E.g. the property below
/**
* #var EntityManager|ObjectManager
*/
protected $entityManager;
When using "Alt + Insert" you get a menu at cursor location. Choose "Getters/Setters". In the pop-up, select "entityManager" and check the box at the bottom for "fluent setters". Then the code below is generated for you:
/**
* #return ObjectManager|EntityManager
*/
public function getEntityManager()
{
return $this->entityManager;
}
/**
* #param ObjectManager|EntityManager $entityManager
* #return AbstractEventHandler
*/
public function setEntityManager($entityManager)
{
$this->entityManager = $entityManager;
return $this;
}
The closes thing you can do to what you want to do is to use #return with multiple types.
/**
* #param $object
* #return ApiObject|AnotherApiObject|OneMoreApiObject
*/
public static function transactional($object)
{
return TransactionalProxy::newInstance($object);
}
I had a discussion with my Team Lead, regarding UnitTest, the question was,
In UnitTest do we use Object Mocking or use the Real Object?
I was supporting the Object Mocking concept, as we should only input/output data from Objects.
At the end we agreed to use Real object instead of Mocking so the following was my Test
<?php
namespace App\Services\Checkout\Module\PaymentMethodRules;
use App\Library\Payment\Method;
use App\Services\Checkout\Module\PaymentMethodRuleManager;
class AdminRule implements PaymentMethodRule
{
/**
* #var boolean
*/
private $isAdmin;
/**
* #var bool
*/
private $isBankTransferAvailable;
/**
* #param boolean $isAdmin
* #param bool $isBankTransferAvailable
*/
public function __construct($isAdmin, $isBankTransferAvailable)
{
$this->isAdmin = $isAdmin;
$this->isBankTransferAvailable = $isBankTransferAvailable;
}
/**
* #param PaymentMethodRuleManager $paymentMethodRuleManager
*/
public function run(PaymentMethodRuleManager $paymentMethodRuleManager)
{
if ($this->isAdmin) {
$paymentMethodRuleManager->getList()->add([Method::INVOICE]);
}
if ($this->isAdmin && $this->isBankTransferAvailable) {
$paymentMethodRuleManager->getList()->add([Method::BANK_TRANSFER]);
}
}
}
<?php
namespace tests\Services\Checkout\Module;
use App\Library\Payment\Method;
use App\Services\Checkout\Module\PaymentMethodList;
use App\Services\Checkout\Module\PaymentMethodRuleManager;
use App\Services\Checkout\Module\PaymentMethodRules\AdminRule;
class AdminRuleTest extends \PHPUnit_Framework_TestCase
{
const IS_ADMIN = true;
const IS_NOT_ADMIN = false;
const IS_BANK_TRANSFER = true;
const IS_NOT_BANK_TRANSFER = false;
/**
* #test
* #dataProvider runDataProvider
*
* #param bool $isAdmin
* #param bool $isBankTransferAvailable
* #param array $expected
*/
public function runApplies($isAdmin, $isBankTransferAvailable, $expected)
{
$paymentMethodRuleManager = new PaymentMethodRuleManager(
new PaymentMethodList([]),
new PaymentMethodList([])
);
$adminRule = new AdminRule($isAdmin, $isBankTransferAvailable);
$adminRule->run($paymentMethodRuleManager);
$this->assertEquals($expected, $paymentMethodRuleManager->getList()->get());
}
/**
* #return array
*/
public function runDataProvider()
{
return [
[self::IS_ADMIN, self::IS_BANK_TRANSFER, [Method::INVOICE, Method::BANK_TRANSFER]],
[self::IS_ADMIN, self::IS_NOT_BANK_TRANSFER, [Method::INVOICE]],
[self::IS_NOT_ADMIN, self::IS_BANK_TRANSFER, []],
[self::IS_NOT_ADMIN, self::IS_NOT_BANK_TRANSFER, []]
];
}
}
My question is, in Unit Test should is use Real Objects or Object Mocking and why?
Second Question, the given Unit test is right or wrong in terms of Unit testing.
The generic answer to such a generic question is: you prefer to use as much of "real" code as possible when doing unit tests. Real code should be default, mocked code is the exception!
But of course, there are various valid reasons to use mocking:
The "real" code does not work in your test setup.
You want to use your mocking framework also to verify that certain actions took place
Example: the code that you intend to test makes a call to some remote service (maybe a database server). Of course that means that you need some tests that do the end to end testing. But for many tests, it might be much more convenient to not do that remote call; instead you would use mocking here - to avoid the remote database call.
Alternatively, as suggested by John Joseph; you might also start with mocking all/most dependencies; to then gradually replace mocking with real calls. This process can help with staying focused on testing exactly "that part" that you actually want to test (instead of getting lost in figuring why your tests using "real other code" is giving you troubles).
IMHO I think it would be good if the original code could be tested directly without any mocking as this would make it less error-prone, and would avoid the debate that if the mocked object behaves almost the same as the original one, but we are not living in the world of unicorns anymore, and mocking is a necessary evil or it is not? This remains the question.
So I think I can rephrase your question to be when to use dummy, fake, stub, or mock?
Generally, the aforementioned terms are known as Test doubles.
As a start, you can check this answer here
Some of the cases when test doubles might be good:
The object under test/System Under Test (SUT) a lot of dependencies, that are required for initialization purposes, and these dependencies would not affect the test, so these dependencies can be dummy ones.
/**
* #inheritdoc
*/
protected function setUp()
{
$this->servicesManager = new ServicesManager(
$this->getDummyEntity()
// ........
);
}
/**
* #return \PHPUnit_Framework_MockObject_MockObject
*/
private function getDummyEntity()
{
return $this->getMockBuilder(Entity\Entity1::class)
->disableOriginalConstructor()
->setMethods([])
->getMock();
}
SUT has an external dependencies such as an Infrastructure/Resource (e.g. web service, database, cash, file …), then it is a good approach to fake that by using in-memory representation, as one of the reasons to do that is to avoid cluttering this Infrastructure/Resource with test data.
/**
* #var ArrayCollection
*/
private $inMemoryRedisDataStore;
/**
* #var DataStoreInterface
*/
private $fakeDataStore;
/**
* #inheritdoc
*/
protected function setUp()
{
$this->inMemoryRedisDataStore = new Collections\ArrayCollection;
$this->fakeDataStore = $this->getFakeRedisDataStore();
$this->sessionHandler = new SessionHanlder($this->fakeDataStore);
}
/**
* #return \PHPUnit_Framework_MockObject_MockObject
*/
private function getFakeRedisDataStore()
{
$fakeRedis = $this->getMockBuilder(
Infrastructure\Memory\Redis::class
)
->disableOriginalConstructor()
->setMethods(['set', 'get'])
->getMock();
$inMemoryRedisDataStore = $this->inMemoryRedisDataStore;
$fakeRedis->method('set')
->will(
$this->returnCallback(
function($key, $data) use ($inMemoryRedisDataStore) {
$inMemoryRedisDataStore[$key] = $data;
}
)
);
$fakeRedis->method('get')
->will(
$this->returnCallback(
function($key) use ($inMemoryRedisDataStore) {
return $inMemoryRedisDataStore[$key];
}
)
);
}
When there is a need of asserting the state of SUT, then stubs become handy. Usually, this would be confused with a fake object, and to clear this out, fake objects are helping objects and they should never be asserted.
/**
* Interface Provider\SMSProviderInterface
*/
interface SMSProviderInterface
{
public function send();
public function isSent(): bool;
}
/**
* Class SMSProviderStub
*/
class SMSProviderStub implements Provider\SMSProviderInterface
{
/**
* #var bool
*/
private $isSent;
/**
* #inheritdoc
*/
public function send()
{
$this->isSent = true;
}
/**
* #return bool
*/
public function isSent(): bool
{
return $this->isSent;
}
}
/**
* Class PaymentServiceTest
*/
class PaymentServiceTest extends \PHPUnit_Framework_TestCase
{
/**
* #var Service\PaymentService
*/
private $paymentService;
/**
* #var SMSProviderInterface
*/
private $smsProviderStub;
/**
* #inheritdoc
*/
protected function setUp()
{
$this->smsProviderStub = $this->getSMSProviderStub();
$this->paymentService = new Service\PaymentService(
$this->smsProviderStub
);
}
/**
* Checks if the SMS was sent after payment using stub
* (by checking status).
*
* #param float $amount
* #param bool $expected
*
* #dataProvider sMSAfterPaymentDataProvider
*/
public function testShouldSendSMSAfterPayment(float $amount, bool $expected)
{
$this->paymentService->pay($amount);
$this->assertEquals($expected, $this->smsProviderStub->isSent());
}
/**
* #return array
*/
public function sMSAfterPaymentDataProvider(): array
{
return [
'Should return true' => [
'amount' => 28.99,
'expected' => true,
],
];
}
/**
* #return Provider\SMSProviderInterface
*/
private function getSMSProviderStub(): Provider\SMSProviderInterface
{
return new SMSProviderStub();
}
}
If the behavior of SUT should be checked then mocks most probably will come to the rescue or stubs (Test spy), it can be detected as simple as that most probably no assert statements should be found. for example, the mock can be setup to behave like when it get a call to X method with values a, and b return the value Y or expect a method to be called once or N of times, ..etc.
/**
* Interface Provider\SMSProviderInterface
*/
interface SMSProviderInterface
{
public function send();
}
class PaymentServiceTest extends \PHPUnit_Framework_TestCase
{
/**
* #var Service\PaymentService
*/
private $paymentService;
/**
* #inheritdoc
*/
protected function setUp()
{
$this->paymentService = new Service\PaymentService(
$this->getSMSProviderMock()
);
}
/**
* Checks if the SMS was sent after payment using mock
* (by checking behavior).
*
* #param float $amount
*
* #dataProvider sMSAfterPaymentDataProvider
*/
public function testShouldSendSMSAfterPayment(float $amount)
{
$this->paymentService->pay($amount);
}
/**
* #return array
*/
public function sMSAfterPaymentDataProvider(): array
{
return [
'Should check behavior' => [
'amount' => 28.99,
],
];
}
/**
* #return SMSProviderInterface
*/
private function getSMSProviderMock(): SMSProviderInterface
{
$smsProviderMock = $this->getMockBuilder(Provider\SMSProvider::class)
->disableOriginalConstructor()
->setMethods(['send'])
->getMock();
$smsProviderMock->expects($this->once())
->method('send')
->with($this->anything());
}
}
Corner cases
SUT has a lot of dependencies which are dependent on other things, and to avoid this dependency loop as we are only interested in testing some methods, the whole object can be mocked, but with having the ability to forward the calls to the original methods.
$testDouble = $this->getMockBuilder(Entity\Entity1::class)
->disableOriginalConstructor()
->setMethods(null);
As per Ahmed Kamal's answer, it worked as expected.
I tested the below sample.
Foo.php
<?php
class Foo
{
/**
* Tell Foo class Name
* #param string $name
* #return string
*/
public function tellName(string $name = 'Josh'): string
{
return 'Hi ' . $name;
}
}
FooTest.php
<?php
include('Foo.php');
use PHPUnit\Framework\TestCase;
class FooTest extends TestCase
{
/**
* PHPUnit testing with assertEquals
* #return void
*/
public function testTellName()
{
// create the class object
$mockObj = $this->getMockBuilder(Foo::class)
->disableOriginalConstructor()
->setMethods(null)
->getMock();
// get the object function result by passing the method parameter value
// pass different parameter value to get an invalid result
$result = $mockObj->tellName('John');
// validate the result with assertEquals()
$this->assertEquals('Hi John', $result);
}
}
Error and Success results:
Cheers!
I am using Netbeans 8 for a Symfony2 project.
I have created a factory class for my model queries (they are static calls and mess up testing).
E.g
<?php
namespace My\Custom\Bundle\Classes\Factories;
use My\Custom\Bundle\Model\UserQuery;
class QueryFactory
{
/**
* Class name
* #access public
*/
const CLASS_NAME = __CLASS__;
/**
* newUserQuery()
*
* Creates a new user query object.
* #access public
* #return My\Custom\Bundle\Model\UserQuery
*/
public function newUserQuery()
{
return UserQuery::create();
}
}
What I want is for the auto complete to work on a variable that is created from a factory method (in this case the Propel methods for the User query).
<?php
namespace My\Custom\Bundle\Controller;
use My\Custom\Bundle\Classes\Factories\QueryFactory;
class ReportingController
{
private $queryFactory;
public function __construct(QueryFactory $query_factory)
{
$this->queryFactory = $query_factory;
}
public function fubar()
{
$user = $this->queryFactory->newUserQuery();
// now want auto complete on the $user (in this case the propel methods)
// $user->filterById(1);
}
}
Any ideas?
I think the problem is #return pointing to My\Custom\Bundle\Classes\Factories\My\Custom\Bundle\Model\UserQuery
try changing it to this
/**
* ...
* #return UserQuery
*/
Without the use statement it should be like this
/**
* ...
* #return \My\Custom\Bundle\Model\UserQuery
*/
How can code completion occur with phpDoc blocks loaded using the T_OBJECT_OPERATOR without having to preset the variables as is shown is the source below?
The only class that matters is the parentExample as it set's the needed $cc that does offer a working solution but it is not desired to preset variables in this manner.
The example code shows the undesired solution and multiple non-working attempts.
As code completion is based on previously set information, preferred to use the full example script not just pieces. Also, as it does relate to phpDocumentor basic phpDoc blocks were included as well. It is desired that these docBlocks get loaded as part of the code completion not just named objects.
<?php
/**
* This is a parent class.
*
* #package Examples/doubledVars
*/
class parentExample
{
/* #var $a parentExample */
public $a;
/**
* This is a var named b
* #var $b parentExample
*/
public $b;
public $c;
public $cc;
// notice^ <------------------------------------------------------SEE ME
/**
* A basic contructor
*/
public function __construct()
{
echo '::PE Class initiated::';
$this -> a = 'we are value "a" in the parent class';
$this -> b = 'we are value "b" in the parent class';
$this -> c = 'we are value "c" in the parent class';
}
}
/**
* This is an Example of doubling occuring due to failed to __construct()
*
* #package Examples/doubledVars
*/
class doubledVars extends parentExample
{
/**
* Value is obtained via parent constuctor.
*
* #return string assigned during construction of parent class.
*/
public function getA()
{
return $this -> a;
}
}
/**
* This is an Example of no doubling occuring due to __construct()
*
* #package Examples/doubledVars
*/
class noDouble extends parentExample
{
/**
* an empty constructor used to prevent doubling during construction.
* child class makes use of parent constructor unless it has it's own.
* or none exsist.
*/
public function __construct()
{
}
/**
* Empty string return
*
* Shows an example of returning values set based on the constructor
* class. In this case there is no default values set at any point, but
* rather value is assigned during the construction of a object.
*
* #return string This string is empty
*/
public function getB()
{
return $this -> b;
}
}
/**
* This is an Example of no doubling occuring due to __construct()
* #see noDouble
*
* #package Examples/codeCompletion
*/
class codeCompletion extends parentExample
{
/**
* #see noDouble::__construct()
*/
public function __construct()
{
//empty constructor prevents doubling
}
public function getC()
{
return $this -> c;
}
}
/** #var $parentExampleDV parentExample */
$parentExampleDV = new parentExample;
// Tried this for Code completion, it did not work <------------------SEE ME
/** #var $doubledVars doubledVars */
$parentExampleDV->doubledVars = new doubledVars;
/* output on next 'echo' will be as follows */
//::PE Class initiated::::PE Class initiated::we are in the parent class
echo '##'.$parentExampleDV->doubledVars->getA().'##';// NO CC <-------SEE ME
echo '<br><br>----------<br><br>';
/** #var $parentExampleDV parentExample */
$parentExampleND = new parentExample;
// Tried this for Code completion, it did not work <------------------SEE ME
/** #var $parentExample->noDouble noDouble */
$parentExampleND -> noDouble = new noDouble;
/* output on next 'echo' will be as follows */
//we are in the parent class
echo '!!'.$parentExampleND->noDouble->getB().'!!';// NO CC <----------SEE ME
echo '<br><br>----------<br><br>';
$parentExampleCC = new parentExample;
$parentExampleCC->cc = new codeCompletion;
echo '##'.$parentExampleCC->cc->getC().'##';//CC working <------------SEE ME
echo '<br><br>----------<br><br>';
I guess It is not possible at this time...