I am using Laravel contracts in my application to decouple the application could from the framework code. Mainly though, I find it easier to see when a class is doing too much at a glance - our legacy projects suffered from 'hidden facades' being peppered all over the place.
use Illuminate\Console\Command;
use Illuminate\Contracts\Filesystem\Factory as File;
class MyClass extends Command
{
public function __construct(File $file)
{
$this->file = $file;
}
public function handle()
{
$this->file->put('/here.txt', 'stuff');
}
}
The problem comes when trying to mock them. If I mock the contract an run the test, the mock is not used in place of the contract.
use Illuminate\Contracts\Filesystem\Factory as File
MyClassTest
{
public function my_example_test()
{
$fileSystem = m::mock(File::class);
$fileSystem->shouldReceive('put')->once();
$this->app->instance(File::class, $fileSystem);
$this->artisan('my-custom-command');
}
}
When I inspect the $file
property I can see of course that laravel used the concrete implementation (obviously). Except when I try and mock the concrete implementation, it too is used instead of the mock.
use Illuminate\Config\Repository as File;
MyClassTest
{
public function my_example_test()
{
$fileSystem = m::mock(File::class);
$fileSystem->shouldReceive('put')->once();
$this->app->instance(File::class, $fileSystem);
$this->artisan('my-custom-command');
}
}
I tried mocking both but this doesn't work either. I am doing integration tests hence why I am calling the command using artisan. Apparantly there is a slightly easier way for unit tests but this does not help in my situation.
Aucun commentaire:
Enregistrer un commentaire