Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Model Factory without connection to database

I would like to use Laravel's Model Factory in some PHPUnit tests. The only thing I want to do is make a Model instance without saving it to database.

Why the Model Factory needs connection to database? These tests must pass on CI environment without configured database.

When I create Model manually by new App\Model($dataArray), tests pass and the connection is not needed.

I am using Model Factory in other places, so I would like to reuse it in that tests, to avoid code duplication.

I am using MongoDB and jenssegers/laravel-mongodb library, but I am guessing that it has no matter - in pure Eloquent and e.g. MySQL database, the issue would be the same.

Test that works without database:

class ModelTransformerTest extends TestCase
{
    public function testTransformMinimalModelData()
    {
        $data = [
            '_id' => $faker->md5,
            'email' => $faker->email,
        ];

        $model = new App\Model($data);
        // […];
    }
}

My Model Factory

$factory->defineAs(Model::class, 'base', function ($faker) {
    return [
        '_id' => $faker->md5,
        'email' => $faker->email,
    ];
});

Test that needs database connection:

class ModelTransformerTest extends TestCase
{
    public function testTransformMinimalModelData()
    {
        $model = factory(App\Model::class, 'base')->make();
        // […];
    }
}

Full stack trace:

Error: Class 'MongoDB\Driver\Manager' not found

app\vendor\mongodb\mongodb\src\Client.php:56
app\vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Connection.php:147
app\vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Connection.php:37
app\vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\MongodbServiceProvider.php:27
app\vendor\illuminate\database\DatabaseManager.php:173
app\vendor\illuminate\database\DatabaseManager.php:68
app\vendor\illuminate\database\Eloquent\Model.php:3282
app\vendor\illuminate\database\Eloquent\Model.php:3248
app\vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Eloquent\Model.php:523
app\vendor\jenssegers\mongodb\src\Jenssegers\Mongodb\Eloquent\Model.php:284
app\vendor\illuminate\database\Eloquent\Model.php:443
app\vendor\illuminate\database\Eloquent\Model.php:281
app\vendor\illuminate\database\Eloquent\FactoryBuilder.php:142
app\vendor\illuminate\database\Eloquent\Model.php:2286
app\vendor\illuminate\database\Eloquent\FactoryBuilder.php:143
app\vendor\illuminate\database\Eloquent\FactoryBuilder.php:106
app\tests\phpunit\Transformers\ModelTransformerTest.php:25
\php\pear\PHPUnit\TextUI\Command.php:176
\php\pear\PHPUnit\TextUI\Command.php:129
like image 330
user1292810 Avatar asked Aug 10 '16 20:08

user1292810


People also ask

Can I use Laravel model without a database?

Yes, you can use a sort of Laravel Model without a Database (offline as you phrase it). Please refer to jenssegers/laravel-model. Basically it's a class implementing ArrayAccess, ArrayableInterface, JsonableInterface with some states and behaviours as needed.

What Laravel version is the defaultdbnamesolutionprovider?

3 This check appeared in Laravel 5.6.29, through the Ignition service's DefaultDbNameSolutionProvider. The solution message is a bit misleading, since it presumes you want to use a database.

What is eloquent base class in Laravel?

It provides an eloquent-like base class that can be used to build custom models in Laravel 4. Jenssegers\Model like Illuminate\Database\Eloquent\Model implements ArrayAccess, ArrayableInterface, JsonableInterface.

What are the two database names Laravel recognizes as default?

†The two database names Laravel recognizes as default are "laravel"and "homestead". Share Improve this answer Follow answered Sep 12 '19 at 13:51 bishopbishop 33.8k99 gold badges9393 silver badges125125 bronze badges 0 Add a comment | 3 Every change you make to the .envfile you need to restart your server.


2 Answers

Do you try using DatabaseTransactions?

For example

use Illuminate\Foundation\Testing\DatabaseTransactions;
class ModelTransformerTest extends TestCase
{
    use DatabaseTransactions;
}
like image 80
David L Avatar answered Sep 30 '22 19:09

David L


I don't think this is currently possible. The make() method calls newModelInstance() which tries to set a database connection.

You can review the source code yourself.

like image 30
Camilo Avatar answered Sep 30 '22 19:09

Camilo