Test containing $this->expectsEvents() always passes - laravel

The following test always passes in my Laravel 5.2 app upgraded from 5.1:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class EventTest extends TestCase
{
public function tearDown()
{
Mockery::close();
}
public function testExample()
{
$this->expectsEvents(App\Events\Foo::class);
}
}
This is despite the App\Events\Foo class not even existing. I've tested the same test in a fresh 5.2 install and it fails as expected. I've looked over the upgrade guide and all relevant non-core code to see whether there's something I've missed that's changed between 5.1 and 5.2 but I can't figure it out. Any ideas?

You need to execute parent tearDown method:
public function tearDown()
{
Mockery::close();
parent::tearDown();
}

Related

Target [Illuminate\Database\Eloquent\Model] is not instantiable while building

Peeps, I'm lost. Tried everything and after 5 hours of searching through the 10th page of Google hits, I give up. Maybe I just dont know how to ask Google the correct keywords..
I have this scenario: In lumen app, lets call it X, I have require custom packages CRUD and Storage, Storage is using functionality of CRUD.
StorageService has:
use Crud\Services\BaseService;
class StorageService extends BaseService{}
And Crud\BaseService has constructor, that uses Model:
use Illuminate\Database\Eloquent\Model;
class BaseService
{
protected $model;
public function __construct(Model $model)
{
$this->model = $model;
}
}
When I try to do anything with my app X, I get error:
Target [Illuminate\Database\Eloquent\Model] is not instantiable while building [Lumee\Storage\Services\StorageService]
I cannot get my head around how to get to proper class of Model, since I saw, that Model is abstract class.
Also, I'm using this CRUD package successfully in another App, only difference is, there CRUD is used directly in app, not via some other package. I'm confused, why there is working without any additional bindings and service registering..
EDIT: Added some binding into StorageServiceProvider (boot and register methods):
$this->app->bind(BaseService::class, function(){
return new BaseService(new Model());
});
And registered StorageServiceProvider in my boostrap/app.php:
$app->register(Storage\Providers\StorageServiceProvider::class);
Thing still returns same error. I tried with binding in CrudServiceProvider, nope.
you can't get object from abstract class (Model class) to solve this try this :
use Illuminate\Database\Eloquent\Model;
class BaseService
{
protected $model;
}
suppose your model is (Storage) :
use Crud\Services\BaseService;
class StorageService extends BaseService{
public function __construct(Storage $model)
{
$this->model = $model;
}
}

Laravel Livewire error when I add a constructor to call a service class

I've got a piece of code I want to reuse. I've read this Laravel cleaner code article and this other Laravel Services Pattern article, where I have realized I can reuse code in several places of the application by using services classes.
In this case, I created a new MyService class, inside a new folder app/Services/MyService.
namespace App\Services;
class MyService
{
public function reuse_code($param){
return void;
}
}
The problem comes when I want to call the class through the constructor inside a Livewire class component, as follows:
<?php
namespace App\Http\Livewire;
use App\Services\MyService;
use Livewire\Component;
use Livewire\WithPagination;
class LivewireTable extends Component
{
use WithPagination;
private $myClassService;
public function __construct(MyService $myService)
{
$this->myClassService = $myService;
}
public function render()
{
$foo = $this->myClassService->reuse_code($param);
return view('my.view',compact('foo'));
}
}
The error displayed is the following:
Argument 1 passed to App\Http\Livewire\LivewireTable::__construct()
must be an instance of App\Services\MyService, string given
(However, If I use a trait, there are no problems. But I am afraid then my traits collide as previous experiences)
How do I fix it? What am I missing?
Livewire's boot method Runs on every request, immediately after the component is instantiated, but before any other lifecycle methods are called
Here's the solution worked for me.
Solved
Just like #IGP said, reading in the livewire docs it says:
In Livewire components, you use mount() instead of a class constructor
__construct() like you may be used to.
So, my working code is as follows:
<?php
namespace App\Http\Livewire;
use App\Services\MyService;
use Livewire\Component;
use Livewire\WithPagination;
class LivewireTable extends Component
{
use WithPagination;
private $myClassService;
public function mount(MyService $myService)
{
$this->myClassService = $myService;
}
public function render()
{
$foo = $this->myClassService->reuse_code($param);
return view('my.view',compact('foo'));
}
}

PHPUnit tests failing after adding a ViewServiceProvider for sharing data to views

I am relatively new to testing so please forgive me if this a stupid question.
All my tests are failing after I added a ViewServiceProvider to share data with the views.
The error is:
Illuminate\Database\QueryException : SQLSTATE[HY000]: General error: 1 no such table: policies (SQL: select "name", "slug" from "policies")
My tests are making use the the refresh database trait:
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
...
}
Here is an example of the ViewServiceProvider:
namespace App\Providers;
use App\Models\Policy;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider
{
public function register(): void{...}
public function boot(): void
{
view()->share('policies', Policy::all(['name', 'slug']));
}
}
Every works when browsing the site on front end. Am i missing something? Why are the tests failing?
I will appreciate suggestions on how to make the tests pass.
Edit
It makes total sense what #Donkarnash said but it's also confusing because according to the docs:
So, what if we need to register a view composer within our service provider? This should be done within the boot method. This method is called after all other service providers have been registered, meaning you have access to all other services that have been registered by the framework
See https://laravel.com/docs/8.x/providers#the-boot-method
I found the solution. Creating a view composer solved the problem.
namespace App\Http\View\Composers;
use App\Models\Policy;
use Illuminate\View\View;
class PolicyComposer
{
public function compose(View $view): void
{
$view->with('policies', Policy::all(['name', 'slug']));
}
}
Then I referenced the composer in the ViewServiceProvider
namespace App\Providers;
use App\Models\Policy;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider
{
public function register(): void{...}
public function boot(): void
{
view()->composer('*', PolicyComposer::class);
}
}

cartalyst extensions' routes only set after first test

Please help I'm using Laravel 5.5 with Cartalyst Platform 7.0 and Phpunit 6.0. I have been trying a lot to install extensions in a testing environment but when the first test runs the extensions routes are not defined so the test returns 404. The second test and the rest of the tests pass because the routes now exist. If I echo(count(\Route::getRoutes())) the first test it is 11 and the rest it is 329.
TestCase
<?php
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Facades\Artisan;
use Sentinel;
abstract class TestCase extends BaseTestCase
{
use TestData, CreatesApplication;
public function setUp()
{
parent::setUp();
$this->app['Illuminate\Contracts\Http\Kernel']->disableMiddleware();
Sentinel::getUserRepository()->setModel(\App\Models\User::class);
Sentinel::getPersistenceRepository()->setUsersModel(\App\Models\User::class);
$this->setUpDatabase();
}
protected function setUpDatabase()
{
Artisan::call('migrate');
Artisan::call('extension:install');
Artisan::call('extension:enable');
}
}

Laravel dependency injection into custom non-controller class fails in PHPUnit

all.
For a Laravel project I'm working on, I've started to use Dependency Injection in order to mock classes in my tests. However, I've found that if I try to inject into a custom class with no explicit parent, two things are true:
The dependency injection works correctly when running the application
The injection fails when running tests in PHPUnit
Here is some sample code similar to what I'm using:
DemoController
// The controller we're testing
class DemoController extends Controller
{
// The injection and constructor
private $helpLayer1;
public function __construct(HelpLayer1 $helpLayer1)
{
$this->helpLayer1 = $helpLayer1;
}
...
// The test function I call
public function testDeps()
{
$this->helpLayer1->testLayer1();
}
}
HelperLayer1
// Our first helper class
class HelperLayer1
{
private $helpLayer2;
public function __construct(HelpLayer2 $helpLayer2)
{
$this->helpLayer2 = $helpLayer2;
}
...
// The testing function
public function testLayer1()
{
// When called via route, this dumps the actual object
// When called via test, this returns null
dd($this->helperLayer2);
}
}
Helper1ServiceProvider
class Helper1ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer1', function()
{
return new HelperLayer1(App::make('HelperLayer2'));
});
}
[OR]
public function register()
{
$this->app->bind('HelperLayer1', 'HelperLayer1');
}
}
Helper2ServiceProvider
class Helper2ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('HelperLayer2', 'HelperLayer2');
}
}
I'm relatively new to using DI, so I'm not entirely sure that this set-up is correct, but I'm at a loss.
Any help would be greatly appreciated! Thank you!

Resources