54

I want to seed database when I use this

 public function run()
{
    $users = factory(app\User::class, 3)->create();
}

Add three user in database but when I use this

 public function run()
{
    $Comment= factory(app\Comment::class, 3)->create();
}

Show me error

[InvalidArgumentException]
Unable to locate factory with name [default] [app\Comment].

paranoid
  • 6,799
  • 19
  • 49
  • 86

17 Answers17

101

Some times it could be due to importing the wrong TestCase

use PHPUnit\Framework\TestCase; [WRONG: and throws this error]


use Tests\TestCase; [CORRECT]

Ayeni TonyOpe
  • 1,651
  • 2
  • 12
  • 6
  • 4
    Same. Using `php artisan make:test MyTest --unit` passed the example test. But was indeed using: `use PHPUnit\Framework\TestCase;` Thanks! – Damon Feb 06 '20 at 23:28
  • 5
    It's really an odd behavior Laravel includes its own abstract `TestCase` class to my codebase but does not intend to use it when it generates test with `make:test`. – Eray Erdin Mar 05 '20 at 10:48
  • 10
    `PHPUnit\Framework\TestCase` should be used for **unit** tests, while Laravel's `Tests\TestCase` is for feature tests. Unit tests must test code in isolation. They shouldn't even boot the Laravel framework. It's not "wrong," this decision is correct and by design. A unit test should never access a database, or anything outside of a single class/method, really. – hackel Apr 13 '20 at 23:07
  • This saved my day. I chose to move my test to Feature as the explanation of @hackel makes sense – Ria Weyprecht Sep 30 '20 at 09:32
91

If nothing helps with PHPUnit.

For those of readers who stuck with the same issue in tests, I found out that I forgot to add parent::setUp() in setUp method.

Darmen Amanbay
  • 4,869
  • 3
  • 29
  • 50
  • 4
    Thanks for pointing that out, I was looking in all the wrong places. – Tomhah Feb 15 '19 at 01:30
  • 3
    Probably saved me an entire day of pulling my hair out, considering everything else was right. – Brandon May 23 '19 at 17:34
  • 1
    Solved my problem. I thought it's not necessary to have the call to the parent class, but apparently it's required! – Ehsan Aug 21 '19 at 04:38
  • After I defined a __construct method in my local TestCase class which all my tests extend, I had to run parent::setUp() to it in order to not override the default behaviour. – Nict Aug 28 '19 at 20:20
  • 1
    This was the problem in my case too. Immediately I removed the `setup()` method, my tests began running. – Oluwatobi Samuel Omisakin Sep 27 '19 at 11:34
49

By default the laravel installation comes with this code in the database/factories/ModelFactory.php File.

$factory->define(App\User::class, function (Faker\Generator $faker) {
    return [
        'name' => $faker->name,
        'email' => $faker->email,
        'password' => bcrypt(str_random(10)),
        'remember_token' => str_random(10),
    ];
});

So you need to define a factory Model before you use it to seed database. This just uses an instance of Faker Library which is used to generate fake Data for seeding the database to perform testing.

Make sure You have added a similar Modal Factory for the Comments Model.

So your Comments Model Factory will be something like this :

$factory->define(App\Comment::class, function (Faker\Generator $faker) {
    return [
        'comment' => $faker->sentence,
         // Any other Fields in your Comments Model 
    ];
});
Mohan
  • 4,677
  • 7
  • 42
  • 65
  • 2
    And when you take a look at `line 129` in https://github.com/illuminate/database/blob/master/Eloquent/FactoryBuilder.php you'll see why @Angry Coder is right. At the moment there's no definition for your Comment class. – Ben Fransen Apr 05 '16 at 09:33
19

This can also happen when you are running the command factory()->create() from php artisan tinker. Make sure you save the file database/factories/ModelFactory.php before opening tinker

Agu Dondo
  • 12,638
  • 7
  • 57
  • 68
14

I'm using laravel 5.5 and for that doing this is bit different. You have to create CommentFactory.php inside \database\factories directory and add this inside,

$factory->define(App\Comment::class, function (Faker\Generator $faker) {
    return [
        'comment' => $faker->sentence,
         // Any other Fields in your Comments Model 
    ];
});

And add this,

$Comment= factory(\App\Comment::class, 3)->create();

instead of

$Comment= factory(app\Comment::class, 3)->create();

I just wanted to add this since I'm facing the same issue for later version and this thread helped me a lot to fix it.

vimuth
  • 5,064
  • 33
  • 79
  • 116
12
  1. Step -   Make sure CommentFactory is using Comment instead of Model.

    use App\Comment ...

    $factory->define(Comment::class, function (Faker $faker){
    
  2. Step - Verify that the names are correct in CommentsTableSeeder.

    use App\Comment ...

    public function run() { factory(Comment::class, 3)->create(); }

Good luck!

Darmen Amanbay
  • 4,869
  • 3
  • 29
  • 50
Cherma Ramalho
  • 373
  • 3
  • 7
  • 1
    I want to note that, that even with it looks obvious, the use App\Comment is not stated in the docs, making me think the factory creation was 'magical'. That was my problem, that missing use. – Absulit Sep 05 '18 at 23:34
12

if you had this issue while using a unit test, this may solve your problem. Extends your class with

Tests\TestCase

instead of

PHPUnit\Framework\TestCase

M.abdelrhman
  • 958
  • 14
  • 24
5

In my case the error was that I've imported the wrong test base class. Instead of extending Laravel's Tests\TestCase I imported the TestCase class from PHPUnit. Silly, but it took me quite some time to figure this out.

4

I'm using Laravel Framework 5.7.19. And in my case, my factory file is generated from command line make:factory. The default model in the file is:

$factory->define(Model::class, ...

You should change the name Model to the thing you exactly want to use, in my case it is \App\InterviewQuestion, so it becomes:

$factory->define(\App\InterviewQuestion::class, ...
Yarco
  • 763
  • 9
  • 18
3

This could be a cache problem. You can resolve it executing the commands following commands.

php artisan clear-compiled
composer dump-autoload
php artisan optimize
Abhilash Asokan
  • 338
  • 1
  • 6
  • For me this caused more issues since it saved my config files so they didn't get overwritten by the phpunit.xml environment values – Robin Castlin May 14 '20 at 09:29
3

None of the answers above did work for me. The best way to fix this error entirely is by registering your factories in TestCase class like that:

<?php

namespace Vendo\Package\Tests;

use Vendor\Package\InboxServiceProvider;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;

class TestCase extends \Orchestra\Testbench\TestCase
{
  public function setUp(): void
  {
    parent::setUp();
    // additional setup

    $this->app->make(EloquentFactory::class)->load(__DIR__ . '/../database/factories');
  }
user2682025
  • 656
  • 2
  • 13
  • 39
  • 2
    You are using `orchestral/testbench`, not the standard Laravel TestCase. The question makes no mention of this third-party package, so your answer does not apply. In addition, Testbench has its own method to do this for you: `$this->withFactories(__DIR__.'/factories');`. Laravel's TestCase automatically loads factories when booting the framework in a feature test. – hackel Apr 13 '20 at 23:13
  • @hackel is the real mvp this is the answer if you use orchestra – darryn.ten Jan 25 '21 at 02:51
2

I was trying to test Model Factory from tinker. I had created model factory as explained in above thread and other Laravel docs. But it would not run and threw an InvalidArgumentException with message

Unable to locate factory with name [default] [/App/Game]

I was running it in Tinker command line as:

factory('\App\Game')->create();

After some time, I found that problem was the leading backslash \. I ran it like below and it worked fine.:

factory('App\Game')->create();

Silly thing, but may help someone.

AS Mackay
  • 2,831
  • 9
  • 19
  • 25
Mihir Kagrana
  • 479
  • 4
  • 4
0

none of the answers worked for me so I delete my factory and create it again (every this is same with the previous factory) and this problem solved for me

yas17
  • 401
  • 1
  • 3
  • 14
0

I had the same problem. Tried everything. Nothing worked. Then I exited Tinker and started it up again and it worked!

le0li0n
  • 1
  • 1
0

In my case, the problem arose because I was using

factory('App\schedule')->create();

Instead of

factory('App\Schedule')->create();

The first letter in "Schedule" was capitalized, so check your spelling, it could be the problem.

Gamopo
  • 1,600
  • 1
  • 14
  • 22
0

Note Few points to remember for Laravel 8+ :

1. Replace

use PHPUnit\Framework\TestCase;

With

use Tests\TestCase;

2. Add

use RefreshDatabase;

use WithFaker;

in your test class.

3. New way of using factories in Laravel tests is :

Post::factory()->create();

For More details see the attached screens :

PostFactory

Post Model

PostController

posts view

post test file

web routes for posts

Aadhar
  • 3
  • 5
0

In my case this issue arose because I hadn't actually made the factory I was trying to call - I had made a bunch of models at once and just forgot to create that one factory!

Abraham Brookes
  • 1,720
  • 1
  • 17
  • 32