laravel-modules
laravel-modules copied to clipboard
Problem with Factory creation
Versions:
- laravel-modules Version: 11.1.4
- Laravel Version: 11.9
- PHP Version: 8.3
Description:
When I make a factory and I want to run a test there is a problem.
Steps To Reproduce:
- make a factory
- call the factory in a test
Console error:
FAILED Modules\Financial\Tests\Feature\FinancialServiceTest > service can deposit funds Error
Class "Database\Factories\Modules\Financial\Models\AccountFactory" not found
at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:833
829▕ public static function factoryForModel(string $modelName)
830▕ {
831▕ $factory = static::resolveFactoryName($modelName);
832▕
➜ 833▕ return $factory::new();
834▕ }
835▕
836▕ /**
837▕ * Specify the callback that should be invoked to guess factory names based on dynamic relationship names.
+2 vendor frames
3 Modules/Financial/tests/Feature/FinancialServiceTest.php:29
I've resolved the solution with :
creating app/Providers/ModulesServiceProvider.php file with:
<?php
declare(strict_types=1);
namespace App\Providers;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class ModulesServiceProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
}
/**
* Bootstrap services.
*/
public function boot(): void
{
// For each Factory inside config('modules.namespace')/*/database/factories
// call the factory att Modules\*\Database\Factories and not at Database\Factories\Modules\*\Database\Factories\ModuleName + Factory
Factory::guessFactoryNamesUsing(function (string $modelName) {
if (str_starts_with($modelName, config('modules.namespace', 'Modules\\'))) {
// get the first part of the string before Models and get the last part of the string for the model name
$modelNameArr = explode('\\', $modelName);
// get index of Models
$index = array_search('Models', $modelNameArr);
// get the first part of the string before Models index value
$moduleNamespace = implode('\\', array_slice($modelNameArr, 0, $index));
// get the last part of the string for the model name
$modelNameModel = end($modelNameArr);
return $moduleNamespace . '\\Database\\Factories\\' . $modelNameModel . 'Factory';
}
return 'Database\\Factories\\' . Str::afterLast($modelName, '\\') . 'Factory';
});
}
}