Yesterday I discovered a model factories but I got a problem with loading model factories from my vendor packages while running unit test implemented in base application. Is that even possible? I ended with an error which tells me that factory cannot be found "... [default]".
Sure, yeh, it's possible. You'd just need to write the code to do it.
Feel free to discuss on the forums.
I investigated that model factories are searched only in /database/factories but I want to load some from /vendor/name/package/database/factories/ but it does not work. My test is located in /tests , not in /vendor/name/package/tests and that's the problem. After analyzing L5 code I am not sure how it could even work ;)
once again... after closing ticket, please, could anybody answer? ;)
@appcia : i faced the same issue. I found the solution is to re-register the EloquentFactory class, for example in your TestCase setUp() method:
// Override Model Factory Path
$this->app->singleton(EloquentFactory::class, function ($app) {
$faker = $app->make(FakerGenerator::class);
return EloquentFactory::construct($faker, __DIR__.('/../src/database/factories'));
});
This is far from elegant, but it's the only solution AFAIK.
I'm pretty sure what @RemiCollin has there will override existing model registrations, check this out, works well for me....
https://github.com/laravel/internals/issues/311
Basically create this function in your service provider...
/**
* Register factories.
*
* @param string $path
* @return void
*/
protected function registerEloquentFactoriesFrom($path)
{
$this->app->make(EloquentFactory::class)->load($path);
}
You'll need to add use use Illuminate\Database\Eloquent\Factory as EloquentFactory;
before your class declaration.
Then in your register methods just do...
$this->registerEloquentFactoriesFrom(__DIR__.'/../factories');
and populate that folder as you are used to when creating factories in laravel/database/factories
Thank you very much.
I did like you:
Modules Provider.
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
//........
public function boot()
{
$this->registerEloquentFactoriesFrom(__DIR__.'/../factories');
}
protected function registerEloquentFactoriesFrom($path)
{
$this->app->make(EloquentFactory::class)->load($path);
}
And all succeed.
Lets say I created my package model factory in
package/src/database/factories/MyFactory.php
and I have my service provider in
package/src/MyServiceProvider.php
then inside MyServiceProvider.php boot() function add the code to publish MyFactory.php to the project factory folder
public function boot()
{
$this->publishes([
__DIR__.'/database/factories/MyFactory.php' => database_path('factories/MyFactory.php')
],'myfactory');
}
Then finally publish your factory using publish command
php artisan vendor:publish --tag=myfactory
Most helpful comment
I'm pretty sure what @RemiCollin has there will override existing model registrations, check this out, works well for me....
https://github.com/laravel/internals/issues/311
Basically create this function in your service provider...
You'll need to add use
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
before your class declaration.Then in your register methods just do...
and populate that folder as you are used to when creating factories in laravel/database/factories