
php
🚀
laravel
🚀
behat
🚀
bdd
🚀
Mockery Behat and Laravel
This is a quick view of using this library https://github.com/laracasts/Behat-Laravel-Extension and a Mockery Trait (should be included soon but for now put the below in your features/bootstrap
folder and run composer dump
).
The example here is a method that looks like this
features/bootstrap/ExampleContext.php
$partial = Mockery::mock(\App\Broadcasts\ColumnsAndRowsDoneProcessingEmail::class, [$this->segment])->makePartial();
$partial->shouldReceive('sendEmail')->never();
$repo = App::make(\App\JobsRepository::class);
$partial->handle($repo);
When this is done running I would get pass BUT if I change it never
to once
and run it again I still get green :(
But I need to include the Mockery. In my case I made this trait that will allow me to also tests and mock events.
<?php
trait MockeryTrait
{
public $firedEvents = [];
public $beforeApplicationDestroyedCallbacks = [];
/**
* @AfterScenario
*/
public function reviewMocks()
{
if ($this->app) {
foreach ($this->beforeApplicationDestroyedCallbacks as $callback) {
call_user_func($callback);
}
$this->app->flush();
$this->app = null;
}
if (class_exists('Mockery')) {
Mockery::close();
}
$this->beforeApplicationDestroyedCallbacks = [];
}
protected function beforeApplicationDestroyed(callable $callback)
{
$this->beforeApplicationDestroyedCallbacks[] = $callback;
}
/**
* Specify a list of events that should be fired for the given operation.
*
* These events will be mocked, so that handlers will not actually be executed.
*
* @param array|string $events
* @return $this
*
* @throws \Exception
*/
public function expectsEvents($events)
{
$events = is_array($events) ? $events : func_get_args();
$this->withoutEvents();
$this->beforeApplicationDestroyed(function () use ($events) {
$fired = $this->getFiredEvents($events);
if ($eventsNotFired = array_diff($events, $fired)) {
throw new Exception(
'These expected events were not fired: ['.implode(', ', $eventsNotFired).']'
);
}
});
return $this;
}
/**
* Mock the event dispatcher so all events are silenced and collected.
*
* @return $this
*/
protected function withoutEvents()
{
$mock = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
$mock->shouldReceive('fire')->andReturnUsing(function ($called) {
$this->firedEvents[] = $called;
});
$this->app->instance('events', $mock);
return $this;
}
/**
* Filter the given events against the fired events.
*
* @param array $events
* @return array
*/
protected function getFiredEvents(array $events)
{
return $this->getDispatched($events, $this->firedEvents);
}
/**
* Filter the given classes against an array of dispatched classes.
*
* @param array $classes
* @param array $dispatched
* @return array
*/
protected function getDispatched(array $classes, array $dispatched)
{
return array_filter($classes, function ($class) use ($dispatched) {
return $this->wasDispatched($class, $dispatched);
});
}
/**
* Check if the given class exists in an array of dispatched classes.
*
* @param string $needle
* @param array $haystack
* @return bool
*/
protected function wasDispatched($needle, array $haystack)
{
foreach ($haystack as $dispatched) {
if ((is_string($dispatched) && ($dispatched === $needle || is_subclass_of($dispatched, $needle))) ||
$dispatched instanceof $needle) {
return true;
}
}
return false;
}
}
This pulls in a trait Laravel uses in PHPUnit.
So now when I run that test I get red and when I set it back to zero
I get green!