Laravel custom Helpers, Facades, and Testing Fakes

In this post, I want to show you how you can create a custom Helper, Facade, and most importantly Testing Fakes.

Let’s consider that we want to create a custom helper named SSH. This helper is going to connect to a remote server via ssh and execute some commands.

Commands

Since we might have many commands, I would create an interface first.

<?php

And then an example command.

<?php

Helper

Alright. Now we want to create a Helper to use the commands. I rather create it in app/Helpers` path.

<?php

Facade

To use this Helper in our application we’ll use Laravel’s Facades.

<?php

Now, Let’s register our Facade in the AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}

/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->bind('ssh', function () {
return new \App\Helpers\SSH;
});
}
}

Perfect! We can use the helper in the application by simply calling the facade.

\App\Facades\SSH::exec(new DirectoryListCommand());

To make it easy to use, You can register the SSH Facade in your config/app.php under the aliases

'aliases' => [
...

Then you can use it like bellow

SSH::exec(new DirectoryListCommand());

Testing

When it comes to testing, The problem is you can’t really test the SSH because it is connecting to a remote server, and in the testing environment you don’t have a remote server! So what we can do?!

The answer is faking! We must fake the exec command.

Let’s create a fake SSH class. I would like to create in app/Support/Testing path.

<?php

namespace App\Support\Testing;

use PHPUnit\Framework\Assert as PHPUnit;

class SSHFake
{
/**
* @var \App\SSHCommands\Command
*/
protected $executedCommand;

/**
* @param \App\SSHCommands\Command $command
* @return void
*/
public function exec($command)
{
$this->executedCommand = get_class($command);
}

/**
* @param \App\SSHCommands\Command $command
* @return void
*/
public function assertExecuted($command)
{
if (!$this->executedCommand) {
PHPUnit::fail("No command executed");
}

PHPUnit::assertTrue(
true,
$this->executedCommand === $command
);
}
}

Let me explain the idea. I just simulated the SSH helper here with a small difference which means that I faked it. instead of executing the command on the remote server, I am adding the command’s class name to the executedCommand property. And then, in the assertExecuted method, I am making sure that the command is executed (stored in the executedCommand property) 😊

The final step is to make the Facade recognize the faked Helper.

Let’s back to the SSH Facade and make a small change.

<?php

// app/Facades/SSH.php

namespace App\Facades;

use Illuminate\Support\Facades\Facade;
use App\Support\Testing\SSHFake;

/**
* Class SSH
*
* @package App\Facades
*
* @method static exec($command)
* @method static assertExecuted($command)
*/
class SSH extends Facade
{
/**
* Replace the bound instance with a fake.
*
* @return \App\Support\Testing\SSHFake
*/
public static function fake()
{
static::swap($fake = new SSHFake());

return $fake;
}

/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'ssh';
}
}

I’ve created a static method named fake which returns an instance of the faked one! I’ve used the swap method of the Facade facade :)

And now we can test the Helper very easily. Here is an example test:

<?php

namespace Tests\Feature;

use App\Facades\SSH;
use App\SSHCommands\DirectoryListCommand;
use Tests\TestCase;

class ExampleTest extends TestCase
{
public function test_ssh_command()
{
SSH::fake();

SSH::exec(new DirectoryListCommand());

SSH::assertExecuted(DirectoryListCommand::class);
}
}

That’s it! 🎉

Thanks for reading this post. Hope you enjoyed it!

I’ll be happy to read your comments about this.