I am trying to write some tests with a Mockery Spy. However, it doesn't seem like the "spied upon" code is executed when I'm using a spy.
Is the code actually executed when using a Mockery spy?
Here is what I tested:
// In my test:
$spy = $this->spy(FeedManager::class);
// Controller
resolve(FeedManager::class)->createResponse();
// FeedManger::createResponse()
public static function createResponse(Builder $builder)
{
dd("here i am"); // this never gets called unless I remove the spy
}
Apparently, the "spy code" is not supposed to run. Found this quote from the docs.
The \Mockery::spy() method call is actually a shorthand for calling
\Mockery::mock()->shouldIgnoreMissing(). The shouldIgnoreMissing
method is a “behaviour modifier”.
I am developing a Laravel application and doing the unit test. Now, I am having a bit of an issue with faking and un-faking Laravel event in the unit test. What I am trying to do is something like this.
public function test_something()
{
Event::fake();
//Do somethng
//Then I want to stop faking event here something like this
Event::stopFaking(); //maybe
}
I think my code is self-explanatory. How can I achieve something like that in Laravel?
https://laravel.com/docs/5.7/mocking
If you only want to fake event listeners for a portion of your test, you may use the fakeFor method:
$order = Event::fakeFor(function () {
$order = factory(Order::class)->create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// Events are dispatched as normal and observers will run ...
$order->update([...]);
Everything inside the function() {} will have faked events. Everything outside will function normally.
The Event::fake function is defined in Illuminate\Support\Facades\Event.
We can see that there is a fakeFor method that only fakes it during the execution of a callback method, then restores the original behavior. You can use it like this:
public function test_something()
{
Event::fakeFor(function () {
//Do somethng
});
}
As a Laravel developer it is often useful to read the source code, there are lots of nice bits and pieces in this framework that are not documented!
I have function that calls out to another function in the same class. I'm trying to test if that method is called in my unit tests however can't find a way to mock it.
Here is an example of the method call
public function follow($user_id, $followsfeed, $target_user_id)
{
$news_feeds = $this->getNewsFeeds($user_id);
}
I want to mock the method getNewsFeed and assert it is being called when I execute follow.
What is the best way to achieve this. as I can't workout how to create an internal mocked object.
You can use a partial mocks, as example on your test class, you can do:
public function test_follow()
{
$mock = Mockery::mock('App\Services\SomeService')->makePartial();
$mock->shouldReceive('getNewsFeeds')
->once()
->with("id1","id2")
->andReturn($someNews);
$mock-> follow("id1","id2");
}
You can also use the PHPUnit test-doubles
Hope this help
Im really curious how does codeigniter achieve something like this:
$this->upload->do_upload($field_name)
it looks like method chaining, but it's not. How would the structure of this look in plain OOP?
I suppose its not as simple as..?
public function upload()
{
// stuff
return $this;
}
public function do_upload()
{
// stuff
return $foo;
}
Cheers!
When you load the library in your controller it's actually doing something like this behind the scene.
include 'system/libraries/Upload.php';
$this->upload = new CI_Upload();
Now you have "$this->upload" ready to use,
Next when you call "$this->upload->do_upload()" you're actually calling a method within the library.
On the other hand Method chaining, is just a matter of making methods returns an instance of the same object, You can review this in libraries code in CodeIgniter 3 on GitHub.
Where most library uses method chaining now.
I need that some code be executed before any MvcEvent::EVENT_BOOTSTRAP listener get execute. Evidently Module::onBootstrap is no an option. I end with the following code:
class Module
{
function init(\Zend\ModuleManager\ModuleManager $moduleManager)
{
$moduleManager->getEventManager()->attach(
MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000);
}
}
I don't want have hard code the array(ClassX, 'StaticMethodOfClassX') reference but get it from the service manager. My problem is that I don't know how to get an service manager reference inside the module's init method. Any help? or this is impossible in ZF2 right now? Whatever variant to this schema or opinion will be appreciate too ;)
EDIT:
I will clarify "Evidently Module::onBootstrap is no an option", cos may be is not so trivial ;)
Modules Module::onBootstrap methods are executed when the event MvcEvent::EVENT_BOOTSTRAP is triggered, but the attachment of each module's Module::onBootstrap method to that event depend of the order in which modules were loaded. Due to, the order in which a specific Module::onBootstrap method will be executed depend on what other modules exist and how other modules affect the order in which that specific module will be loaded. Beside, whatever listener attached to the MvcEvent::EVENT_BOOTSTRAP event with priority greater than 1 will be execute before any module Module::onBootstrap method, example the ViewManager::onBootstrap listener. So, to achieve what I want
I need that some code be executed before any
MvcEvent::EVENT_BOOTSTRAP listener get execute
modules obBootstrap methods are not an option.
This is a very old post but since no answer has been accepted and I recently needed to achieve the same thing, I thought I'd share my solution.
The reason I needed to access the ServiceManager before the Bootstrap event is triggered, was so I could manipulate the merged configuration with values retrieved from the database.
Problem:
The example found in the Zend documentation shows how to manipulate the merged configuration, but at that particular time the Service manager is empty, making it impossible to retrieve things like database adapters etc.
Solution:
In your module class, implement the interface InitProviderInterface and add the appropriate method.
public function init(ModuleManagerInterface $moduleManager)
{
$eventManager = $moduleManager->getEventManager();
$eventManager->attach(ModuleEvent::EVENT_LOAD_MODULES_POST, [$this, 'onLoadModulesPost']);
}
The EVENT_LOAD_MODULES_POST event will get invoked after the EVENT_MERGE_CONFIG event but before the EVENT_BOOTSTRAP event is triggered. Also at this particular time the ServiceManager will contain all the factories, invokable classes you're wanting to access.
Your callback method may look something like.
public function onLoadModulesPost(ModuleEvent $event)
{
/* #var $serviceManager \Zend\ServiceManager\ServiceManager */
$serviceManager = $event->getParam('ServiceManager');
$configListener = $event->getConfigListener();
$configuration = $configListener->getMergedConfig(false);
$someService = $serviceManager->get('Your/Custom/Service');
$information = $someService->fetchSomeInformation();
$configuration = array_merge($configuration, $information);
$configListener->setMergedConfig($configuration);
$event->setConfigListener($configListener);
$serviceManager->setAllowOverride(true);
$serviceManager->setService('Config', $configuration);
$serviceManager->setAllowOverride(false);
}
You can get it off the MvcEvent
$locator = $event->getTarget()->getServiceLocator()->get('YourObject')
If you don't have access to the event, you can set the event as a property on the Module class on bootstrap, and then use it in your init method whenever.
public function onBootstrap($event) {
$this->setMvcEvent($event);
}
function init(\Zend\ModuleManager\ModuleManager $moduleManager)
{
$locator = $this->mvc_event->getTarget()->getServiceLocator()->get('YourClass');
$moduleManager->getEventManager()->attach(
MvcEvent::EVENT_BOOTSTRAP, array(ClassX, 'StaticMethodOfClassX'), 20000);
}
Are you using ZfcBase in your application? The AbstractModule has a boostrap method (not onBootstrap) which is executed by this event handler in the init method
$sharedManager->attach('Zend\Mvc\Application', 'bootstrap', function($e) use ($instance, $moduleManager) {
$app = $e->getParam('application');
...
$instance->bootstrap($moduleManager, $app);
});
Of course you can use this approach without ZfcBase.
Then you can implement Zend\ServiceManager\ServiceLocatorAwareInterface:
public function bootstrap(\Zend\ModuleManager\ModuleManager $moduleManager, \Zend\Mvc\ApplicationInterface $app){
$this->setServiceLocator($app->getServiceManager());
parent::bootstrap($moduleManager, $app);
}
public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){
$this->_serviceLocator = $serviceLocator;
return $this;
}
public function getServiceLocator(){
return $this->_serviceLocator;
}
Maybe a bit later but hope it will help somebody else. At the init point there is no much services at the Service Manager but you can access it:
public function init(ModuleManager $moduleManager)
{
$sm = $moduleManager->getEvent()->getParam('ServiceManager');
$applicationConfig = $sm->get('applicationconfig');
var_dump($applicationConfig['modules']);
}
In this case we are retrieving the module names.
This is better idea.
class module
public function onBootstrap(MvcEvent $e)
{
$sm = $app->getServiceManager();
$config = $sm->get('config');
and this is all.