[PHP] InvalidArgumentException : Unable to locate factory with name [default]

발단

Laravel Framework로 TDD를 진행중에 Unit Test를 하기 위해 artisan 콘솔을 이용하여 TaskTest 라는 이름의 테스트 클래스를 생성하였습니다.

1
$ php artisan make:test TaskTest --unit

코드는 간단했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

namespace Tests\Unit;

use App\Project;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\TestCase;

class TaskTest extends TestCase
{
use RefreshDatabase;

/**
* @test
*/
public function it_belongs_to_a_project()
{
$task = factory('App\Task')->create();
$this->assertInstanceOf(Project::class, $task->project);
}
}

해당 테스트를 생성 후 아래와 같이 PHPUnit으로 해당 테스트를 실행하였더니

1
$ ./vendor/bin/phpunit --filter it_belongs_to_a_project

아래 이미지와 같은 에러가 나왔습니다.

InvalidArgumentException : Unable to locate factory with name [default] [App\Task]

과연 무엇이 문제일까 싶어 해당 모델의 migration이 제대로 안된걸까요?

migrate 명령어도 실행해보았고, Controller Test에서 사용할때에는 문제가 없었지만 factory 코드도 다시 작성 해보았습니다.

구글링으로 정광섭님의 위키를 참고했을때는 factory에 클래스가 제대로 설정된게 아닌 경우라 하여,

factory('App\Task')factory(Task::class)factory(\App\Task::class) 모두 테스트 해보았는데 모두 동작을 안했고,

Laracast와 StackoverFlow에서는 phpunit의 setup 메소드를 상속하여,

parent::setup() 을 호출하고, factory를 호출하면 해결된다는 답변들도 확인하였으나, 제게 맞는 해결 방법은 아니였습니다.

하지만 라라캐스트 질문의 어떤 답변에서는
--unit으로 생성한 테스트 클래스가 상속하는 TestCase 클래스가 \Tests\TestCase 가 아닌 \PHPUnit\Framework\TestCase여서 발생했다는 내용이 있었습니다.

해결

저도 이걸 확인하고 바로 위의 코드를 아래와 같이 변경하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace Tests\Unit;

use App\Project;
use Illuminate\Foundation\Testing\RefreshDatabase;
- use PHPUnit\Framework\TestCase;
+ use Tests\TestCase;

class TaskTest extends TestCase
{
use RefreshDatabase;

/**
* @test
*/
public function it_belongs_to_a_project()
{
$task = factory('App\Task')->create();
$this->assertInstanceOf(Project::class, $task->project);
}
}

네임스페이스를 확인할 생각은 전혀 하지 못했는데, 일반적인 테스트 클래스는 모두 use Tests\TestCase; 이렇게 선언되어있었으나

--unit으로 선언했을때는 use PHPUnit\Framework\TestCase;으로 자동 설정되어있었습니다.

아직까지 artisan에서 --unit 옵션을 사용하여 테스트 클래스를 만들었을때 namespace 변경 없이 하는 방법은 찾지 못하였는데,

Illuminate\Foundation\Testing\TestCase 에서 무언가 factory 메소드의 파라미터로 모델을 주입해주는 설정해주는것으로 보입니다.

참고자료

[PHP] InvalidArgumentException : Unable to locate factory with name [default]

https://blog.hodory.dev/2020/01/09/Unable-to-locale-factory-with-name-default/

Author

Hodory

Posted on

2020-01-10

Updated on

2022-08-11

Licensed under

댓글